This Case Study is a guest post written by Keith Kirk, VP Engineering at Underground Elephant. Want your company featured on the official Symfony blog? Send us a proposal or case study to fabien.potencier@sensiolabs.com

How Underground Elephant uses Symfony and IronMQ for success

Message Queues are not a new concept – neither is Push Notifications and surely not HTTP Posts for that matter. However, when you combine these ideas you have a very flexible queueing system.

Sprinkle in a little bit of Symfony's EventDispatcher... suddenly your Symfony application starts to feel a whole lot more responsive. And that feels great.

The Lead Up

Underground Elephant is an online performance marketing company, and provides customer acquisition software for its clients. We're constantly weighing the benefits of hosting our own services vs using cloud-based alternatives. More often than not, in our fast-paced environment – we have bigger fish to fry than dealing with administrating, scaling, and maintaining simple services that, while are important, are not core to our business.

So, when it came to finding ways to increase the responsiveness of our Symfony2 applications and move non-essential processes to the background, we started exploring job queues and messaging.

Admittedly, spinning up an instance of RabbitMQ or ØMQ ain't hard, neither is writing a script that will keep a socket open waiting for new messages.

I guess, frankly, we just didn't want to do it. It was another moving part that my teams had to maintain outside of their applications and more dependencies and infrastructure in our deployment.

Queue Your Cake and Eat it Asynchronously

What I wanted was to keep my dependencies light and in code - maintained by Composer. I wanted a way to write my worker code as simple services within my Symfony application – all maintained within the same repository and deployed just as easily.

I wanted persistence in my queue and a level of failover in case of errors. I wanted hands-off scaling and distribution – and I really wanted someone else to manage it.

So, I wanted a lot, actually.

Enter the Symfony2 QPush Bundle, integrated with IronMQ, Iron.io's cloud message queue as a service.

The bundle integrates push queue providers directly into your Symfony application allowing you to create and manage multiple queues. Subscribers are configurable, allowing differing and/or multiple subscribers per queue.

You can publish messages easily

1
2
3
4
5
6
7
8
9
// src/My/Bundle/ExampleBundle/Controller/MyController.php

public function publishAction()
{
    $message = array('foo' => 'bar');

    // fetch your provider service from the container
    $this->get('uecode_qpush')->get('my_queue_name')->publish($message);
}

The bundle leverages the EventDispatcher to dispatch a MessageEvent when your published messages are received from your queue. Your services are called automatically based on simple tagging which gives a lot of flexibility in chaining services or handling multiple queues in a single service.

Because it utilizes simple services in Symfony, its very easy to re-use your existing code. For us, this made adoption incredibly easy.

Handle Events in Your Services

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// src/My/Bundle/ExampleBundle/Service/ExampleService.php

use Uecode\Bundle\QPushBundle\Event\MessageEvent;
use Uecode\Bundle\QPushBundle\Message\Message;

public function onMessageReceived(MessageEvent $event)
{
    $id         = $event->getMessage()->getId();
    $body       = $event->getMessage()->getBody();
    $metadata   = $event->getMessage()->getMetadata();

    // do some processing
}

Check out the documentation for more information on how to incorporate this into your application.

Push Queues are Awesome!

Push Queues may not appeal to everyone or fit each use case, but there is a ton of up-side to them.

You know that queue you have that's not heavily utilized, but processing each message as soon as possible is incredibly important? Yeah, the one you're polling on the same 5 second interval at 3am that you are at the heaviest time of day. By pushing notifications directly to you application, you can remove that wasted compute, the wasted API calls, and wasted money.

No more daemon, no more cron.

For PHP specifically, threading has always been a sore spot (read, "non-existent"). However, with Push Queues, you can utilize your web server (Apache, Nginx, etc) to handle the threading for you. This also means you can easily scale horizontally by either registering more subscribers or utilizing a cluster of web servers behind a load balancer.

Wrapping Up

The QPush Bundle is open source and openly available to use. We're also very welcome to contributions and feedback. If you have any questions, please visit us on github.com/uecode/qpush-bundle!