Files changed (18)
+A `ConsumerSet <#affinitic.zamqp.consumerset.ConsumerSet>`_ is a set of consumers that are listening to the same `BrokerConnection <connection.html#affinitic.zamqp.interfaces.IBrokerConnection>`_ grouped into one object.
+We also define a factory to ease creation of a ConsumerSet, see `IConsumerSetFactory <#affinitic.zamqp.interfaces.IConsumerSetFactory>`_
We use `grok <http://grok.zope.org>`_ to define our zope components. This avoids us to write too much
-This means that we a message is received it is registered in the transaction so that if someone acknoledge the message, the acknoledgement will be send only if the transaction is correctly commited. Also if a message is acknoledge and for some reason the transaction is aborted, the message acknoledgement never gets sent.
+This means that we a message is received it is registered in the transaction so that if someone acknoledge the message, the acknoledgement will be send to the message broker only if the transaction is correctly commited. Also if a message is acknoledge and for some reason the transaction is aborted, the message acknoledgement never gets sent.
+Once a Zope instance is started, after instance initialization (ZServers startup, ZODB startup, zcml parsing ...) an event (`DatabaseOpenedWithRootEvent`) is trigerred.
+We have a subscriber that catch this event. At first it reads the the instance configuration (zope.conf) to see if there is any ampq connection defined.
+If there is an amqp connection defined, it creates a new thread with a *Processor* that connect to the specified amqp connection and which consume messages on exchange related to this connection. The thread is constantly waiting for new message.
+A processor has a list of worker threads, that's why we call it `MultiProcessor`. Once a message arrive in the *Processor* thread, it delegates processing of the message to one of these worker thread (`ConsumerProcessor`).
+In the Zope 2 configuration of an instance (zope.conf), there is a section called *product-config*. In this section you can define product specific configuration in the instance.
+The service will then create a *Processor* on the connection with id `CONNECTIONID` (see BrokerConnection).
+All new incoming messages will be notified on the site manager of the site which is on path `SITEPATH`.
+The `ConnectionBroker` utility named `connection1` has to be defined in zcml and at least one `Consumer` should exist for this connection.
+The ZODB events are not really present by default in Zope 2. The package `five.dbevent` patch the correct code that enables us to plug our subscriber just after instance initialization.
+One *Processor* (see `MultiProcessor`) thread create a ConsumerSet (see `ConsumerSet`) on the broker connection id given by the configuration.
+Once the ConsumerSet is created, it waits for messages on the different Consumer queues. When a message arrive it create a `ConsumerProcessor` thread
+The `ConsumerProcessor` thread just take the message, register it into the ZODB transaction system and pass it to the zope event system. This allow
+loose coupling of components: as the message is marked with the Consumer interface, it allow us to create the corresponding subscribers for type of message
-The ``receive`` method will call first the ``_markMessage`` which will add our marker interface on the incoming message::
+The ``receive`` method will call first the ``_markMessage`` which will add our marker interface on the incoming message::
+Instead of creating connections for different exchanges on the same virtual host, you can create one
+Then define different consumers (with two different marker interface) and link them to the same connection::
+Now we can define our ConsumerSet which will wait for incoming message on the red and the blue queue.
+To easy consumer set creation, we have defined a factory. The only parameter that the factory takes is
+The ``receive`` method on the consumer set will call first the ``_markMessage`` method which will add
+Then the ``receive`` method will call the ``_adaptMessage`` method that can adapt our message. Let's
+If we pass a red message, it is also printed and adapted with the default adapter for message, ``MessageWrapper``::
+ <affinitic.zamqp.message.MessageWrapper object ...> received on red queue with body "World is Red"
-If the message is transaction aware and is acknoledged then the message broker receives acknoledgement
+If the message is transaction aware and is acknoledged then the message broker receives acknoledgement
+To test the configuration that will be coming from the zope.conf file we change the global config object that is given by ``getConfiguration``::
+As we can't receive messages in this test from a message broker, we mock the iterconsume method from the ConsumerSet so that it just log the fact that it should be consuming and don't make it blocking::
+We can at last read the configuration and initialise the two thread, one for consuming messages on connection bar and another for consuming messages on connection foo::