<commit_before># RabbitMqBundle #

## About ##

The RabbitMqBundle incorporates messaging in your application via [RabbitMq](http://www.rabbitmq.com/) using the [php-amqplib](http://github.com/videlalvaro/php-amqplib) library.

The bundle implements several messaging patterns as seen on the [Thumper](https://github.com/videlalvaro/Thumper) library. Therefore publishing messages to RabbitMQ from a Symfony2 controller is as easy as:

    $msg = array('user_id' => 1235, 'image_path' => '/path/to/new/pic.png');
    $this->get('old_sound_rabbit_mq.upload_picture_producer')->publish(serialize($msg));

Later when you want to consume 50 messages out of the `upload_pictures` queue, you just run on the CLI:

    $ ./app/console rabbitmq:consumer -m 50 upload_picture

All the examples expect a running RabbitMQ server.

This Bundle was presented at [Symfony Live Paris 2011](http://www.symfony-live.com/paris/schedule#session-av1) conference. See the slides [here](http://www.slideshare.net/old_sound/theres-a-rabbit-on-my-symfony):

## Installation ##

The following instructions have been tested on a project created with the [Symfony2 Standard 2.0.6](http://symfony.com/download?v=Symfony_Standard_2.0.6.tgz)

Put the RabbitMqBundle and the [php-amqplib](http://github.com/videlalvaro/php-amqplib) library into the deps file:

    ...
    [RabbitMqBundle]
    git=http://github.com/videlalvaro/RabbitMqBundle.git
    target=/bundles/OldSound/RabbitMqBundle

    [php-amqplib]
    git=http://github.com/videlalvaro/php-amqplib.git
    target=videlalvaro/php-amqplib
    ...

Register the bundle and library namespaces in the `app/autoload.php` file:

    $loader->registerNamespaces(array(
        ...
        'OldSound'         => __DIR__.'/../vendor/bundles',
        'PhpAmqpLib'       => __DIR__.'/../vendor/videlalvaro/php-amqplib',
        ...
    ));

Add the RabbitMqBundle to your application's kernel:

    public function registerBundles()
    {
        $bundles = array(
            ...
            new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(),
            ...
        );
        ...
    }


## Usage ##

Configure the `rabbitmq` service in your config:

    old_sound_rabbit_mq:
        connections:
            default:
                host:      'localhost'
                port:      5672
                user:      'guest'
                password:  '<PASSWORD>'
                vhost:     '/'
        producers:
            upload_picture:
                connection: default
                exchange_options: {name: 'upload-picture', type: direct}
        consumers:
            upload_picture:
                connection: default
                exchange_options: {name: 'upload-picture', type: direct}
                queue_options:    {name: 'upload-picture'}
                callback:         upload_picture_service
        ...

Here we configure the connection service and the message endpoints that our application will have. In this example your service container will contain the service `rabbitmq.upload_picture_producer` and `rabbitmq.upload_picture_consumer`. The later expects that there's a service called `upload_picture_service`.

If you don't specify a connection for the client, the client will look for a connection with the same alias. So for our `upload_picture` the service container will look for an `upload_picture` connection.

## Producers, Consumers, What? ##

In a messaging application, the process sending messages to the broker is called __producer__ while the process receiving those messages is called __consumer__. In your application you will have several of them that you can list under their respective entries in the configuration.

### Producer ###

A producer will be used to send messages to the server. In the AMQP Model, messages are sent to an __exchange__, this means that in the configuration for a producer you will have to specify the connection options along with the exchange options, which usually will be the name of the exchange and the type of it.

Now let's say that you want to process picture uploads in the background. After you move the picture to its final location, you will publish a message to server with the following information:

    public function indexAction($name)
    {
        ...
        $msg = array('user_id' => 1235, 'image_path' => '/path/to/new/pic.png');
        $this->get('old_sound_rabbit_mq.upload_picture_producer')->publish(serialize($msg));
        ...
    }

As you can see, if in your configuration you have a producer called __upload\_picture__, then in the service container you will have a service called __rabbitmq.upload\_picture\_producer__.

The next piece of the puzzle is to have a consumer that will take the message out of the queue and process it accordingly.

### Consumers ###

A consumer will connect to the server and start a __loop__  waiting for incoming messages to process. Depending on the specified __callback__ for such consumer will be the behavior it will have. Let's review the consumer configuration from above:

    ...
    consumers:
        upload_picture:
            connection: default
            exchange_options: {name: 'upload-picture', type: direct}
            queue_options:    {name: 'upload-picture'}
            callback:         upload_picture_service
    ...

As we see there, the __callback__ option has a reference to an __upload\_picture\_service__. When the consumer gets a message from the server it will execute such callback. If for testing or debugging purposes you need to specify a different callback, then you can change it there.

Apart from the callback we also specify the connection to use, the same way as we do with a __producer__. The remaining options are the __exchange\_options__ and the __queue\_options__. The __exchange\_options__ should be the same ones as those used for the __producer__. In the __queue\_options__ we will provide a __queue name__. Why?

As we said, messages in AMQP are published to an __exchange__. This doesn't mean the message has reached a __queue__. For this to happen, first we need to create such __queue__ and then bind it to the __exchange__. The cool thing about this is that you can bind several __queues__ to one __exchange__, in that way one message can arrive to several destinations. The advantage of this approach is the __decoupling__ from the producer and the consumer. The producer does not care about how many consumers will process his messages. All it needs is that his message arrives to the server. In this way we can expand the actions we perform every time a picture is uploaded without the need to change code in our controller.

Now, how to run a consumer? There's a command for it that can be executed like this:

    $ ./app/console rabbitmq:consumer -m 50 upload_picture

What does this mean? We are executing the __upload\_picture__ consumer telling it to consume only 50 messages. Every time the consumer receives a message from the server, it will execute the configured callback. By default the consumer will process messages in an __endless loop__ for some definition of _endless_.

### Callbacks ###

Here's an example callback:

    <?php

    //src/Sensio/HelloBundle/Consumer/UploadPictureConsumer.php

    namespace Sensio\HelloBundle\Consumer;

    use Symfony\Component\DependencyInjection\ContainerAware;
    use OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface;

    class UploadPictureConsumer extends ContainerAware implements ConsumerInterface
    {
        public function execute($msg)
        {
            //Process picture upload.
            //$msg will be what was published from the Controller.
        }
    }
<commit_msg>updates README<commit_after># RabbitMqBundle #

## About ##

The RabbitMqBundle incorporates messaging in your application via [RabbitMq](http://www.rabbitmq.com/) using the [php-amqplib](http://github.com/videlalvaro/php-amqplib) library.

The bundle implements several messaging patterns as seen on the [Thumper](https://github.com/videlalvaro/Thumper) library. Therefore publishing messages to RabbitMQ from a Symfony2 controller is as easy as:

    $msg = array('user_id' => 1235, 'image_path' => '/path/to/new/pic.png');
    $this->get('old_sound_rabbit_mq.upload_picture_producer')->publish(serialize($msg));

Later when you want to consume 50 messages out of the `upload_pictures` queue, you just run on the CLI:

    $ ./app/console rabbitmq:consumer -m 50 upload_picture

All the examples expect a running RabbitMQ server.

This Bundle was presented at [Symfony Live Paris 2011](http://www.symfony-live.com/paris/schedule#session-av1) conference. See the slides [here](http://www.slideshare.net/old_sound/theres-a-rabbit-on-my-symfony):

## Installation ##

The following instructions have been tested on a project created with the [Symfony2 Standard 2.0.6](http://symfony.com/download?v=Symfony_Standard_2.0.6.tgz)

Put the RabbitMqBundle and the [php-amqplib](http://github.com/videlalvaro/php-amqplib) library into the deps file:

    ...
    [RabbitMqBundle]
    git=http://github.com/videlalvaro/RabbitMqBundle.git
    target=/bundles/OldSound/RabbitMqBundle

    [php-amqplib]
    git=http://github.com/videlalvaro/php-amqplib.git
    target=videlalvaro/php-amqplib
    ...

Register the bundle and library namespaces in the `app/autoload.php` file:

    $loader->registerNamespaces(array(
        ...
        'OldSound'         => __DIR__.'/../vendor/bundles',
        'PhpAmqpLib'       => __DIR__.'/../vendor/videlalvaro/php-amqplib',
        ...
    ));

Add the RabbitMqBundle to your application's kernel:

    public function registerBundles()
    {
        $bundles = array(
            ...
            new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(),
            ...
        );
        ...
    }


## Usage ##

Configure the `rabbitmq` service in your config:

    old_sound_rabbit_mq:
        connections:
            default:
                host:      'localhost'
                port:      5672
                user:      'guest'
                password:  '<PASSWORD>'
                vhost:     '/'
        producers:
            upload_picture:
                connection: default
                exchange_options: {name: 'upload-picture', type: direct}
        consumers:
            upload_picture:
                connection: default
                exchange_options: {name: 'upload-picture', type: direct}
                queue_options:    {name: 'upload-picture'}
                callback:         upload_picture_service
        ...

Here we configure the connection service and the message endpoints that our application will have. In this example your service container will contain the service `rabbitmq.upload_picture_producer` and `rabbitmq.upload_picture_consumer`. The later expects that there's a service called `upload_picture_service`.

If you don't specify a connection for the client, the client will look for a connection with the same alias. So for our `upload_picture` the service container will look for an `upload_picture` connection.

## Producers, Consumers, What? ##

In a messaging application, the process sending messages to the broker is called __producer__ while the process receiving those messages is called __consumer__. In your application you will have several of them that you can list under their respective entries in the configuration.

### Producer ###

A producer will be used to send messages to the server. In the AMQP Model, messages are sent to an __exchange__, this means that in the configuration for a producer you will have to specify the connection options along with the exchange options, which usually will be the name of the exchange and the type of it.

Now let's say that you want to process picture uploads in the background. After you move the picture to its final location, you will publish a message to server with the following information:

    public function indexAction($name)
    {
        ...
        $msg = array('user_id' => 1235, 'image_path' => '/path/to/new/pic.png');
        $this->get('old_sound_rabbit_mq.upload_picture_producer')->publish(serialize($msg));
        ...
    }

As you can see, if in your configuration you have a producer called __upload\_picture__, then in the service container you will have a service called __rabbitmq.upload\_picture\_producer__.

The next piece of the puzzle is to have a consumer that will take the message out of the queue and process it accordingly.

### Consumers ###

A consumer will connect to the server and start a __loop__  waiting for incoming messages to process. Depending on the specified __callback__ for such consumer will be the behavior it will have. Let's review the consumer configuration from above:

    ...
    consumers:
        upload_picture:
            connection: default
            exchange_options: {name: 'upload-picture', type: direct}
            queue_options:    {name: 'upload-picture'}
            callback:         upload_picture_service
    ...

As we see there, the __callback__ option has a reference to an __upload\_picture\_service__. When the consumer gets a message from the server it will execute such callback. If for testing or debugging purposes you need to specify a different callback, then you can change it there.

Apart from the callback we also specify the connection to use, the same way as we do with a __producer__. The remaining options are the __exchange\_options__ and the __queue\_options__. The __exchange\_options__ should be the same ones as those used for the __producer__. In the __queue\_options__ we will provide a __queue name__. Why?

As we said, messages in AMQP are published to an __exchange__. This doesn't mean the message has reached a __queue__. For this to happen, first we need to create such __queue__ and then bind it to the __exchange__. The cool thing about this is that you can bind several __queues__ to one __exchange__, in that way one message can arrive to several destinations. The advantage of this approach is the __decoupling__ from the producer and the consumer. The producer does not care about how many consumers will process his messages. All it needs is that his message arrives to the server. In this way we can expand the actions we perform every time a picture is uploaded without the need to change code in our controller.

Now, how to run a consumer? There's a command for it that can be executed like this:

    $ ./app/console rabbitmq:consumer -m 50 upload_picture

What does this mean? We are executing the __upload\_picture__ consumer telling it to consume only 50 messages. Every time the consumer receives a message from the server, it will execute the configured callback. By default the consumer will process messages in an __endless loop__ for some definition of _endless_.

### Callbacks ###

Here's an example callback:

    <?php

    //src/Sensio/HelloBundle/Consumer/UploadPictureConsumer.php

    namespace Sensio\HelloBundle\Consumer;

    use OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface;

    class UploadPictureConsumer implements ConsumerInterface
    {
        public function execute($msg)
        {
            //Process picture upload.
            //$msg will be what was published from the Controller.
        }
    }

{'fraction_non_alphanumeric': 0.07155003270111183, 'fraction_numerical': 0.004316546762589928, 'mean_word_length': 3.197364809223168, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, 'https://': 2, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3238767', 'n_tokens_mistral': 4128, 'n_tokens_neox': 3905, 'n_words': 1691}