socloz/event-queue-bundle

A Symfony2 bundle that enable asynchonous execution of event listeners.

dev-master 2014-12-30 09:49 UTC

This package is not auto-updated.

Last update: 2024-04-21 01:13:26 UTC


README

A Symfony2 bundle that enable asynchonous execution of event listeners.

As long as some conditions are met, no code changes are required for an application to use the bundle.

The bundle is made of two parts : a listener and a worker.

The listener :

  • is registered for the configured event, with maximum priority,
  • stops propagation of those events,
  • sends the serialized events to the queue.

The worker :

  • builds the list of application listeners for the configured event,
  • listens to the queue and deserializes received events,
  • executes the listeners.

Dependencies

  • beanstalk - other queues can be added

Setup

$loader->registerPrefixes(array(
    [...]
    'Socket_'          => __DIR__.'/../vendor/beanstalk/src',
));
  • configure the service
socloz_event_queue:
    queue_type: beanstalkd
    forward: [ my.event.name, my.event.name ]
    serialize: mongoodm
    beanstalkd:
        host: 127.0.0.1
        tube: event_queue

Other possible configuration options (with default values) :

socloz_event_queue:
    beanstalkd:
        port: 11300
        persistent: true
        timeout: 1
  • start the worker (a process management daemon, like supervisord is recommended) :
$ app/console socloz:event_queue:worker [stop_after]

If used, stop_after enables to worker to stop after a certain number of seconds (warning : the test is done after a job has been executed).

Serializers

Events need to be serialized before being sent. Objects coming from the ORM/ODM usually cannot be serialized/deserialized using PHP builtin classes, therefore the bundle uses dedicated serializers.

For now, 2 basic serializers exist :

  • Mandango (serialize: mandango),
  • MongoDB ODM (serialize: mongoodm).

They assume :

  • that a getId method exists for ORM/ODM objects,
  • that all objects having a getId method come from the ORM/ODM,
  • that objects have been saved before dispatching the event (the remote listener instantiates objects from the DB),
  • that events can be created using the constructor without other method calls,
  • that constructor parameters have the same name as class attributes.

I did not have time/wasn't able to find a solution for those. Feel free to contribute better serializers !

ReflectionClass::newInstanceWithoutConstructor would help, but has only be added in 5.4. Class specific serializers, built during warm-up, would also improve performance if you need to forward a lot of events.

Example event class :

<?php

namespace Socloz\APIBundle\Event\Event;

use Symfony\Component\EventDispatcher\Event;

class CategoryDeleteEvent extends Event
{
    protected $category;

    public function __construct($category)
    {
        $this->category = $category;
    }

    public function getCategory()
    {
        return $this->category;
    }
}

If you need a serializer, it needs to implement the Socloz\EventQueueBundle\Serialize\SerializeInterface interface.

interface SerializeInterface
{
    public function serialize($event);

    public function deserialize($data);
}

It then needs to be registered as a service named socloz_event_queue.serialize.your_serializer_name and configured :

socloz_event_queue:
    serialize: your_serializer_name

Queue

If you want to use another transport (RabbitMQ, Zer0MQ, Gearman, ...), you need to implement the Socloz\EventQueueBundle\Queue\QueueInterface interface.

interface QueueInterface
{
    public function put($job);

    public function get();

    public function delete($job);
}

get is a blocking call. delete is only required if get does not remove jobs from the queue.

The transport class should be registered as a service named socloz_event_queue.queue.

TODO

  • Serializers I wouldn't be ashamed of
  • Beanstalkd timeout & priority configuration

License

This bundle is released under the MIT license (see LICENSE).