The Amazon cloud, explained.

Home / Blog / Featured / Distributed Functors with SQS and PHP

A functor (or function object) is a really common programming pattern; it’s commonly used to implement callbacks. The idea is to pass an object that is invoked by the receiver.

The functor pattern is usually limited to a single process (i.e. wherever the code is executing), but SQS and PHP enable you to take this pattern to a distributed and scalable level.

Let’s illustrate this with an example. Consider a simple class defined in helloworld.php

Hello World PHP

In our code, we will instantiate this class and pass in a message that our object will store.

picture-44

Our $helloWorld object is going to be our functor; in theory, we should be able to pass this object to another recipient, they should be able to invoke methods on it (sayHello in our case). Before we start passing this object around, we need to be able to preserve its state. We can do that by calling the serialize function in PHP.

The serialize function takes our object and stores its state as a string; in many languages, the format used is XML. By default in PHP, it is just some string representation. Our serialized object string will look something like the following:

O:10:"HelloWorld":1:{s:7:"message";s:14:"Hello World!!!";}

This is where SQS comes into play; we will send this serialized string as the body of an SQS message. Whoever receives this message can de-serialize the string into an object again and invoke its functionality.

Before we send our serialized string, it is a good idea to urlencode it first. Some of the characters may interfere with the XML format of an SQS message.

The code to create the queue, serialize and urlencode the object and send it as an SQS message looks as shown below.

picture-451

Notice that we are hiding the implementation of how we are sending the message behind our sendMessage function; all we are doing is constructing the send message request and setting the body to our serialized and urlencoded state.

Since we are using SQS, our code to receive these messages can live in another process. This really helps our scalability because we can run these worker processes on multiple machines if we need to process a large number of messages.

The entire code for our worker is listed below:

picture-46We are using a class called AdaptivePoll to help us out here. I’ll explain this class in another post. For now, just know that it polls a given SQS queue and calls bodyFunction if it finds a message.

When we get a message, notice how we are url-decoding the message and then de-serializing it. When we execute sayHello we should see a Hello World!!! message get printed out - this is the same message we set in our earlier code

SQS is an elegantly simple solution to a wide range of problems; in this case, we can use it to implement a generic, distributed functor pattern.

Comments are closed.