[RFC] Batch

This is a first attempt at creating a Batch overview system in Bernard. It implements some new concepts with fun names. Everything is open for change based on comments.

When you create a batch of messages first you create a `Batch`. This generates an id for the batch and also keeps track of its status (failed, total, successful).

I order to have messages be part of the batch they are assigned though `Batch::assign()`. At this point you have a Batch with assigned messages, theese have not yet been persisted. To persist them give the whole Batch to the producer.

``` php
<?php

$batch = new Batch;
$batch->assign(new DefaultMessage('Email'));

$producer->produce($batch);
```

It is also possible to assign messages to an already existing batch. This is doing by creating a Batch using a specific id, or retrieving a batch for its storage. By producing the batch again its internal list of messages are flushed and the internal list is reset.

``` php
<?php

$batch = new Batch('existing-id');
$batch->assign(new DefaultMessage('Email'));

$producer->produce($batch);
```

As earlier mentioned it is possible to retrieve a Batch status from storage. Currently there is only a Redis implementation.

``` php
<?php

$storage = new RedisStorage($redis);

$batch = $storage->find('batch-id');
$batches = $storage->all();
$batch  = $storage->reload($batch);

// will block until all messages in batch is complete
while ($batch->isRunning()) {
    continue;
}
```

Reloading will return a NEW batch object, so if you have assigned messages that are not yet been produced they will be lost.

Every batch is stored with its storage. This is done in middlewares, one for the producer which updates the Batch total and one for the consumer wich increments failed and/or successful counts.

Theese are registered as normal middlewares.

``` php

$storage = new RedisStorage($redis);

$consumerMiddlewareBuilder->push(function ($next) use ($storage) {
    return new BatchConsumerMiddleware($next, $storage);
});

$producerMiddlewareBuilder->push(function ($next) use ($storage) {
    return new BatchProducerMiddleware($next, $storage);
})
```

For bernard internals this is only possible by adding metadata to Envelope's which is called stamps. This is a hash of additional metadata given to an Envelope when created.

Does this make sense?