Skip to content

Commit

Permalink
Merge pull request #7 from Nyholm/predefined
Browse files Browse the repository at this point in the history
Added a middleware to only publish predefined messages
  • Loading branch information
matthiasnoback committed Apr 6, 2016
2 parents 85d5b0b + 54e5ac1 commit 808a6eb
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 3 deletions.
40 changes: 37 additions & 3 deletions doc/publishing_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ currentMenu: publishing_messages
# Publishing messages

When a `Message` should not be handled by the message bus (i.e. command or event bus) immediately (i.e. synchronously),
it can be *published* to be handled by some other process. This library comes with two strategies for publishing
messages: either a message will always *also* be published, or it will only be published when the message bus isn't able
to handle it because there is no handler defined for it.
it can be *published* to be handled by some other process. This library comes with three strategies for publishing
messages:

1. A message will always *also* be published.
2. A message will only be published when the message bus isn't able to handle it because there is no handler defined for it.
3. A message will be published only if its name exists in a predefined list.

## Strategy 1: Always publish messages

Expand Down Expand Up @@ -78,4 +81,35 @@ Possibly some other process knows how to handle it.

If no command handler was found and the command is published, this will be logged using the provided `$logger`.

## Strategy 3: Only publish predefined messages

This strategy is useful when you know what messages you want to publish.

```php
use SimpleBus\Message\Bus\Middleware\MessageBusSupportingMiddleware;
use SimpleBus\Asynchronous\MessageBus\AlwaysPublishesMessages;
use SimpleBus\Asynchronous\Publisher\Publisher;
use SimpleBus\Message\Message;
use SimpleBus\Message\Name\MessageNameResolver;

// $eventBus is an instance of MessageBusSupportingMiddleware
$eventBus = ...;

// $publisher is an instance of Publisher
$publisher = ...;

// $messageNameResolver is an instance of MessageNameResolver
$messageNameResolver = ...;

// The list of names will depend on what MessageNameResolver you are using.
$names = ['My\\Event', 'My\\Other\\Event'];

$eventBus->appendMiddleware(new PublishesPredefinedMessages($publisher, $messageNameResolver, $names));

// $event is an object
$event = ...;

$eventBus->handle($event);
```

*Continue reading about [consuming messages](consuming_messages.md)*
52 changes: 52 additions & 0 deletions src/MessageBus/PublishesPredefinedMessages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace SimpleBus\Asynchronous\MessageBus;

use SimpleBus\Asynchronous\Publisher\Publisher;
use SimpleBus\Message\Bus\Middleware\MessageBusMiddleware;
use SimpleBus\Message\Name\MessageNameResolver;

class PublishesPredefinedMessages implements MessageBusMiddleware
{
/**
* @var \SimpleBus\Asynchronous\Publisher\Publisher
*/
private $publisher;

/**
* @var MessageNameResolver
*/
private $messageNameResolver;

/**
* @var array names
*/
private $names;

/**
* @param Publisher $publisher
* @param MessageNameResolver $messageNameResolver
* @param array $names an array with names on messages to be published.
*/
public function __construct(Publisher $publisher, MessageNameResolver $messageNameResolver, array $names)
{
$this->publisher = $publisher;
$this->messageNameResolver = $messageNameResolver;
$this->names = $names;
}

/**
* Handle a message by publishing it to a queue (always), then calling the next middleware
*
* {@inheritdoc}
*/
public function handle($message, callable $next)
{
$name = $this->messageNameResolver->resolve($message);
if (in_array($name, $this->names)) {
$this->publisher->publish($message);
}

$next($message);
}
}
93 changes: 93 additions & 0 deletions tests/MessageBus/PublishesPredefinedMessagesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace SimpleBus\Asynchronous\Tests\MessageBus;

use SimpleBus\Asynchronous\MessageBus\PublishesPredefinedMessages;
use SimpleBus\Asynchronous\Publisher\Publisher;
use SimpleBus\Message\CallableResolver\Exception\UndefinedCallable;
use SimpleBus\Message\Name\MessageNameResolver;

class PublishesPredefinedMessagesTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function it_calls_the_next_middleware_and_when_the_message_is_handled_it_does_not_publish_it()
{
$message = $this->dummyMessage();

$nextCallableCalled = false;
$alwaysSucceedingNextCallable = function ($actualMessage) use ($message, &$nextCallableCalled) {
$nextCallableCalled = true;
$this->assertSame($message, $actualMessage);
};

$publisher = $this->mockPublisher();
$publisher
->expects($this->never())
->method('publish');

$nameResolver = $this->mockNameResolver();
$nameResolver->method('resolve')
->willReturn('foo');

$middleware = new PublishesPredefinedMessages($publisher, $nameResolver, ['baz', 'bar']);

$middleware->handle($message, $alwaysSucceedingNextCallable);

$this->assertTrue($nextCallableCalled);
}

/**
* @test
*/
public function it_calls_the_next_middleware_and_when_the_message_has_no_handler_it_publishes_it()
{
$message = $this->dummyMessage();

$nextCallableCalled = false;
$alwaysSucceedingNextCallable = function ($actualMessage) use ($message, &$nextCallableCalled) {
$nextCallableCalled = true;
$this->assertSame($message, $actualMessage);
};

$publisher = $this->mockPublisher();
$publisher
->expects($this->once())
->method('publish')
->with($this->identicalTo($message));

$nameResolver = $this->mockNameResolver();
$nameResolver->method('resolve')
->willReturn('foo');

$middleware = new PublishesPredefinedMessages($publisher, $nameResolver, ['baz', 'foo', 'bar']);

$middleware->handle($message, $alwaysSucceedingNextCallable);

$this->assertTrue($nextCallableCalled);
}

/**
* @return \PHPUnit_Framework_MockObject_MockObject|Publisher
*/
private function mockPublisher()
{
return $this->getMock('SimpleBus\Asynchronous\Publisher\Publisher');
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject|MessageNameResolver
*/
private function mockNameResolver()
{
return $this->getMock('SimpleBus\Message\Name\MessageNameResolver');
}

/**
* @return \PHPUnit_Framework_MockObject_MockObject|object
*/
private function dummyMessage()
{
return new \stdClass();
}
}

0 comments on commit 808a6eb

Please sign in to comment.