11

On my site I'd like to do push notifications of comments like Stackoverflow does. Amazon SNS/SQS seems to provide a framework to do this but I'm having difficulty finding any code/explanation on the web for anything beyond a "hello world" equivalent.

From reading the AWS SNS/SQS documentation it looks like I need the following:

logic:

  1. post comment/answer to a new question
  2. create topic (for first comment/answer only)
  3. publish message
  4. subscribe to topic

PHP on the page where comments are posted (http://mysite.com/postCommentOrAnswer.php):

$comment=$_POST['comment']; //posted comment
require_once 'application/third_party/AWSSDKforPHP/sdk.class.php';
$sns = new AmazonSNS();

$response = $sns->create_topic('SO-like-question-12374940'); //create topic

$response = $sns->publish(
  'arn:aws:sns:us-east-1:9876543210:SO-like-question-12374940',
  $comment
);  //publish comment

$response = $sns->subscribe(
  'arn:aws:sns:us-east-1:9876543210:SO-like-question-12374940',
  'https ',
  'https://mysite.com/notificationsReceiver'
); // Subscribe to notifications

PHP on the page where notifications are received (http://mysite.com/notificationsReceiver.php):

no idea, thoughts?

Obviously, this is not close to being a complete demonstration and probably has some incorrect function calls but I was wondering if someone might be able to help build upon this?

tim peterson
  • 23,653
  • 59
  • 177
  • 299
  • Are you wedded to SQS/SNS for this? I don't think I'd use them for it. – ceejayoz Jul 17 '12 at 17:40
  • Hi @ceejayoz, no I'm not wedded to them for this. I happy to use something else. I just haven't found anything that is comprehensive, yet simply explained to relative PHP newcomers such as myself. I'm also using Codeigniter if you know of any PHP and/or Codeigniter solutions you have in mind. – tim peterson Jul 17 '12 at 17:59
  • For most sites, it's going to be perfectly OK to do this in the main database you're using for the site (MySQL, maybe). – ceejayoz Jul 17 '12 at 19:26
  • @ceejayoz, thanks yes i'm using mysql. This sounds good but could you provide a few more details, perhaps in an answer to this question? My understanding is very minimal. Currently I'm using a `setInterval()` to query my database for new messages on a regular interval but would prefer to do a push system. I just don't know the logic of how to do that. – tim peterson Jul 17 '12 at 19:38
  • @ceejayoz do you have any suggestions/links for how to use PHP to do push notifications? The main thing I'm confused about is how to structure my the page that will receive the messages? – tim peterson Jul 20 '12 at 19:26

1 Answers1

3

Your comment implied that you are not wedded to SQS, so I am answering with a MySQL solution.

Unless you're dealing with so much traffic that messages would actually ever get queued, I'd recommend just a simple MySQL table approach.

I have a site with a MySQL notifications table that looks like this:

CREATE TABLE `notification` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `user_id` INT(11) NOT NULL,
    `notification_type` ENUM('inline','popup') NOT NULL DEFAULT 'inline',
    `html` TEXT NOT NULL,
    `entered_date` DATETIME NOT NULL,
    `display_date` DATETIME NOT NULL,
    `show_once` TINYINT(1) NOT NULL DEFAULT '0',
    `closable` TINYINT(1) NOT NULL DEFAULT '1',
    `destroy_on_close` TINYINT(1) NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`),
    INDEX `user_id` (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM

This table is checked upon page load and the proper notification is displayed according to the notification data. Insertion is done as various actions or events occur on the website.

I'm at well over 10,000 users and so far this approach has not proven to be a bottleneck for the site. I don't expect it to anytime soon, either.

Andy Baird
  • 6,088
  • 4
  • 43
  • 63
  • -@Andy, thanks for this. The one thing I'm still confused about is how to make the notifications be updated after page loading, i.e., in a "push" fashion. Do you know how the "push" works programmatically? – tim peterson Jul 19 '12 at 00:31
  • 1
    The two most common options in PHP land would be long-polling (which Facebook uses quite a bit) or else interval checking as you proposed in your comment previously. Long polling is where a request is made to the server, but the server does not reply to the request until it has data to supply for the response (in this case a notification) or after a timeout threshold is reached and the poll is restarted. Good article here: http://blog.perplexedlabs.com/2009/05/04/php-jquery-ajax-javascript-long-polling/ – Andy Baird Jul 19 '12 at 00:31
  • -@Andy, thanks for the link. I think I'd prefer a push mechanism but I hadn't really ever understood how long polling worked. This link is making it start to make sense... – tim peterson Jul 19 '12 at 00:35
  • -@Andy, also i'm on an Apache server where people always talking about it not being able to support alot of open connections. So even though I haven't launched my site yet, I'd prefer to implement the "right" approach to this now rather than have to reconfigure later to a push approach because I chose not to spend the time to learn how to do it. – tim peterson Jul 19 '12 at 00:38
  • -@Andy, one last question, in the link you sent what's the point of `usleep(25000);`? I assume its just a delay to prevent some kind of havoc wreaking, loop-within-loop cycle, but just wanted to check. – tim peterson Jul 19 '12 at 00:46
  • My hunch is that it prevents the PHP process from completely hogging the server CPU since that makes the loop execute only 40 times a second. – Andy Baird Jul 19 '12 at 01:45
  • If you do not have full control over your web server (or the entire box, to be honest) I'd advise against longpolling. Apache running in it's standard configuration will likely topple over fast with just a small number of users. Keep in mind if someone simply leaves your site open in a tab, they are using up valuable server resources. At very least, benchmark your server and make sure you know how many concurrent users you can support before going with longpolling. – Andy Baird Jul 19 '12 at 01:49
  • i'm a one-man operation so that's what I'm trying to get a handle on all the facts. Yeah, I realize that people often leave a tab open. Currently I've got a setInterval() going every 2 minutes with a setTimeout() after 30 minutes. So 15 requests. Of course I'd prefer a solution that gives real-time updates (not 2min delay) but 40 db queries/sec sounds too much. This is why it appears a push solution would be the way to go. Yes/no? – tim peterson Jul 19 '12 at 02:01
  • It depends on your server. You can easily increase the timeout of the loop to something more reasonable, like once ever 2 seconds instead 40 times per second. Really though, unless you have a site where people aren't moving from page to page much, or things happen very quickly (like SO), I doubt your users will notice too much. That's just my two cents though. You can always add long-polling later and it won't necessarily be "doing it wrong" as long as you architect the code for your notifications correctly. – Andy Baird Jul 19 '12 at 02:14
  • I'd like to enable "things to happen quickly (like SO)". Also, my site is one page so the notification bar won't change unless I implement something. From the business perspective, it seems me that real-time notifications are what cause many sites to get popular. People get easily distracted and it would seem more so on sites they are newer too, so to me optimizing this appears critical. And as a one-man operation it will be challenging enough to deal with customer service/business stuff if the site grows so want to get this out of the way now. – tim peterson Jul 19 '12 at 02:34
  • My server is EC2 microinstance ubuntu LAMP, can support 9 connections/sec which is pitifully low, but unlike application logic, server scaling won't take effort on my part. – tim peterson Jul 19 '12 at 02:35
  • Perfect. Now you know your limitations, so you know exactly *when* you need to upgrade. Good luck! If nothing else you will surely learn a lot. – Andy Baird Jul 19 '12 at 02:36