Amazon SQS (Queuing) Service and PHP

Queuing: something that just needs to happen if background processing needs to be done.  Well, Amazon’s AWS service has that feature and I had to set it up.  Here are some notes on what I did to set it up for a email queuing service.  The first few steps are probably repeats if you are already using the PHP SDK for other services.

1) Get the SDK- http://aws.amazon.com/sdkforphp
First things first, download the SDK from Amazon and put it in a PHP/Apache accessible directory.

2) Get your credentials – http://aws.amazon.com/articles/4261
Follow the directions on this site to get your secret key and access keys.
Next, copy the config-sample.inc.php that is located in the root of the SDK to the same directory with the new name config.inc.php. Use the key information to fill  out theconfig.inc.php and save the file.

3) Run the compatibility test
Go to your localhost at  http://${HTTP_HOST}/${AMAZON_SDK_DIRECTORY}/_compatibility_test/sdk_compatibility_test.php and make sure there’s a green bar at the bottom saying you’re good to go.

4) Watch the videos / Read through the documentation
Seriously, the videos were the best part of the documentation. Easy to follow, said a lot.  http://d1un85p0f2qstc.cloudfront.net/fundamentals_sqs/video.html

PHP Amazon Generic Documentation: http://aws.amazon.com/documentation/sdkforphp/

 

PHP SDK Documentation: http://docs.amazonwebservices.com/AWSSDKforPHP/latest/

5) We got some coding to do.
This should be fairly easy if you followed the videos and checked out the documentation.  I created the queue by hand in the administrator, so I did not need to go through that by code.  My goal was to make two functions: one to add a message to the queue, and one to retrieve and delete it.

First we need to include the SDK

include_once("sdk.class.php");

The addToQueue function is used to push a message onto the queue.  This would be called when the front end of the application needs to send an email or do some background processing.  It’s a very quick action and allows the end user to not have to wait for the entire action to take place before moving on to do something else.

function addToQueue($to, $emailTemplate) {
	//initiate the object
	$sqs = new AmazonSQS();
	$queue_url = "https://queue.amazonaws.com/SOME_NUMBER/QUEUE_NAME";

	//an example array of the message we could sent to the queue
	$arr = array('to' => $to, 'template' => $emailTemplate);
	//json encode the message so that we can easily send multiple variables in the same string
	//	php has json ecoding built in, so it's pretty light
	$message = json_encode($arr);
	//actually add the message to the queuing system
	$addEmailResponse = $sqs->send_message($queue_url, $message);
}

The processMessage function is used to do the actual work.  In reality, this would be called via a cron often and would churn through all of the messages.

function processMessage () {
	$sqs = new AmazonSQS();
	$queue_url = "https://queue.amazonaws.com/SOME_NUMBER/QUEUE_NAME";
	//get a "random" message from the amazon queue
	//	also visibility timeout tells amazon how long to keep the lock on that particular record
	//	this example is using 30 seconds, so that means that we have 30 seconds to send the email
	//	before it can be found again.  This can be changed
	$messageResponse = $sqs->receive_message($queue_url, array( 'VisibilityTimeout' => 30));
	//get the JSON encoded message that is brought with the message
	$message = json_decode($messageResponse->body->ReceiveMessageResult->Message->Body);
	//we need the receipt handle for deletion.  Amazon needs to know which message to delete
	$receiptHandle = $messageResponse->body->ReceiveMessageResult->Message->ReceiptHandle;
	//make sure we found an acutal message and the queue isn't empty
	$everythingHasGoneWell = isset($message);

	if($everythingHasGoneWell)
	{
		//actually send the email.  Email function should return a boolean if it's succesful or not
		$everythingHasGoneWell = sendEmail($message->to, $message->template);
		//if the email was actually sent go ahead, otherwise it will try again when the visibility timeout is met
		if ($everythingHasGoneWell) {
			//delete the message from the queuing system, really we should be checking for response codes throughout the
			//	system, here included.
			$deleteResponse = $sqs->delete_message($queue_url, $receiptHandle);
		}
	}
	else
	{
		//something went wrong or there were no emails in the queue
		print_r("No emails to process.");
	}
}

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s