Skip to content

Commit 41cb103

Browse files
Merge pull request #6 from Nyholm/predefined
Added option to change strategy for publishing events
2 parents b3337e5 + d7e09f8 commit 41cb103

9 files changed

+185
-11
lines changed

composer.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"php": ">=5.4",
1717
"beberlei/assert": "~2.0",
1818
"simple-bus/message-bus": "~2.0",
19-
"simple-bus/asynchronous": "~2.0",
19+
"simple-bus/asynchronous": "~2.1",
2020
"simple-bus/symfony-bridge": "~4.0",
2121
"symfony/framework-bundle": "~2.0|~3.0"
2222
},
@@ -26,7 +26,8 @@
2626
"require-dev": {
2727
"phpunit/phpunit": "~4.0",
2828
"symfony/monolog-bundle": "~2.3",
29-
"satooshi/php-coveralls": "~0.6"
29+
"satooshi/php-coveralls": "~0.6",
30+
"matthiasnoback/symfony-dependency-injection-test": "^0.7"
3031
},
3132
"autoload": {
3233
"psr-4" : { "SimpleBus\\AsynchronousBundle\\" : "src" }

doc/getting_started.md

+12
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,15 @@ simple_bus_asynchronous:
6868
```
6969

7070
This will log consumed messages to the `asynchronous_command_bus` and `asynchronous_event_bus` channels respectively.
71+
72+
## Choose event strategy
73+
74+
When handling events you have two strategies to choose from. Either you publish *all* events to the message queue or
75+
you only publish the events that have a registered subscriber. If your application is the only one that consuming messages
76+
you should consider using the **predefined** strategy. This will reduce the message overhead on the message queue.
77+
78+
```yaml
79+
simple_bus_asynchronous:
80+
events:
81+
strategy: 'predefined' # default: 'always'
82+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace SimpleBus\AsynchronousBundle\DependencyInjection\Compiler;
4+
5+
use SimpleBus\SymfonyBridge\DependencyInjection\Compiler\CollectServices;
6+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
9+
class CollectAsynchronousEventNames implements CompilerPassInterface
10+
{
11+
use CollectServices;
12+
13+
/**
14+
* Get all asynchronous event subscribers and save the name of the event they are listening to.
15+
*
16+
* @param ContainerBuilder $container
17+
*/
18+
public function process(ContainerBuilder $container)
19+
{
20+
$serviceId = 'simple_bus.asynchronous.publishes_predefined_messages_middleware';
21+
if (!$container->hasDefinition($serviceId)) {
22+
return;
23+
}
24+
25+
$names = array();
26+
$this->collectServiceIds(
27+
$container,
28+
'asynchronous_event_subscriber',
29+
'subscribes_to',
30+
function ($key) use (&$names) {
31+
$names[] = $key;
32+
}
33+
);
34+
35+
$container->getDefinition($serviceId)->replaceArgument(2, array_unique($names));
36+
}
37+
}

src/DependencyInjection/Configuration.php

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public function getConfigTreeBuilder()
4343
->arrayNode('events')
4444
->canBeEnabled()
4545
->children()
46+
->enumNode('strategy')
47+
->info('What strategy to use to publish messages')
48+
->defaultValue('always')
49+
->values(['always', 'predefined'])
50+
->end()
4651
->scalarNode('publisher_service_id')
4752
->info('Service id of an instance of Publisher')
4853
->isRequired()

src/DependencyInjection/SimpleBusAsynchronousExtension.php

+11-6
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,7 @@ private function requireBundle($bundleName, ContainerBuilder $container)
5353
{
5454
$enabledBundles = $container->getParameter('kernel.bundles');
5555
if (!isset($enabledBundles[$bundleName])) {
56-
throw new \LogicException(
57-
sprintf(
58-
'You need to enable "%s" as well',
59-
$bundleName
60-
)
61-
);
56+
throw new \LogicException(sprintf('You need to enable "%s" as well', $bundleName));
6257
}
6358
}
6459

@@ -100,5 +95,15 @@ private function loadAsynchronousEventBus(array $config, ContainerBuilder $conta
10095
if ($config['logging']['enabled']) {
10196
$loader->load('asynchronous_events_logging.yml');
10297
}
98+
99+
100+
if ($config['strategy'] === 'always') {
101+
$eventMiddleware = 'simple_bus.asynchronous.always_publishes_messages_middleware';
102+
} else {
103+
$eventMiddleware = 'simple_bus.asynchronous.publishes_predefined_messages_middleware';
104+
}
105+
106+
// insert before the middleware that actually notifies a message subscriber of the message
107+
$container->getDefinition($eventMiddleware)->addTag('event_bus_middleware', ['priority' => 0]);
103108
}
104109
}

src/Resources/config/asynchronous_events.yml

+8-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ services:
1313
public: false
1414
arguments:
1515
- '@simple_bus.asynchronous.event_publisher'
16-
tags:
17-
# insert before the middleware that actually notifies a message subscriber of the message
18-
- { name: event_bus_middleware, priority: 0 }
16+
17+
simple_bus.asynchronous.publishes_predefined_messages_middleware:
18+
class: SimpleBus\Asynchronous\MessageBus\PublishesPredefinedMessages
19+
public: false
20+
arguments:
21+
- '@simple_bus.asynchronous.event_publisher'
22+
- '@simple_bus.event_bus.event_name_resolver'
23+
- []
1924

2025
simple_bus.asynchronous.event_bus.finishes_message_before_handling_next_middleware:
2126
class: SimpleBus\Message\Bus\Middleware\FinishesHandlingMessageBeforeHandlingNext

src/SimpleBusAsynchronousBundle.php

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace SimpleBus\AsynchronousBundle;
44

5+
use SimpleBus\AsynchronousBundle\DependencyInjection\Compiler\CollectAsynchronousEventNames;
56
use SimpleBus\AsynchronousBundle\DependencyInjection\SimpleBusAsynchronousExtension;
67
use SimpleBus\SymfonyBridge\DependencyInjection\Compiler\ConfigureMiddlewares;
78
use SimpleBus\SymfonyBridge\DependencyInjection\Compiler\RegisterHandlers;
@@ -39,5 +40,7 @@ public function build(ContainerBuilder $container)
3940
'subscribes_to'
4041
)
4142
);
43+
44+
$container->addCompilerPass(new CollectAsynchronousEventNames());
4245
}
4346
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace SimpleBus\AsynchronousBundle\Tests\Unit\DependencyInjection\Compiler;
4+
5+
6+
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractCompilerPassTestCase;
7+
use SimpleBus\AsynchronousBundle\DependencyInjection\Compiler\CollectAsynchronousEventNames;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Definition;
10+
11+
class CollectAsynchronousEventNamesTest extends AbstractCompilerPassTestCase
12+
{
13+
protected function registerCompilerPass(ContainerBuilder $container)
14+
{
15+
$container->addCompilerPass(new CollectAsynchronousEventNames());
16+
}
17+
18+
/**
19+
* @test
20+
*/
21+
public function if_compiler_pass_collects_event_names()
22+
{
23+
$serviceId = 'simple_bus.asynchronous.publishes_predefined_messages_middleware';
24+
$middleware = new Definition();
25+
$middleware->addArgument('arg0');
26+
$middleware->addArgument('arg1');
27+
$middleware->addArgument([]);
28+
$this->setDefinition($serviceId, $middleware);
29+
30+
$subscriber = new Definition();
31+
$subscriber->addTag('asynchronous_event_subscriber', ['subscribes_to'=>'foo']);
32+
$this->setDefinition('event_subscriber', $subscriber);
33+
34+
$this->compile();
35+
36+
$this->assertContainerBuilderHasServiceDefinitionWithArgument($serviceId, 2, ['foo']);
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace SimpleBus\AsynchronousBundle\Tests\Unit\DependencyInjection;
4+
5+
6+
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
7+
use SimpleBus\AsynchronousBundle\DependencyInjection\SimpleBusAsynchronousExtension;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
10+
class SimpleBusAsynchronousExtensionTest extends AbstractExtensionTestCase
11+
{
12+
protected function getContainerExtensions()
13+
{
14+
return array(
15+
new SimpleBusAsynchronousExtension('simple_bus_asynchronous')
16+
);
17+
}
18+
19+
protected function getMinimalConfiguration()
20+
{
21+
return ['object_serializer_service_id'=>'my_serializer', 'commands'=>['publisher_service_id'=>'pusher'], 'events'=>['publisher_service_id'=>'pusher']];
22+
}
23+
24+
25+
/**
26+
* @test
27+
*/
28+
public function it_uses_strategy_allways_by_default()
29+
{
30+
$this->container->setParameter('kernel.bundles', ['SimpleBusCommandBusBundle'=>true, 'SimpleBusEventBusBundle'=>true]);
31+
$this->load();
32+
33+
$this->assertContainerBuilderHasServiceDefinitionWithTag('simple_bus.asynchronous.always_publishes_messages_middleware', 'event_bus_middleware', ['priority'=>0]);
34+
}
35+
36+
/**
37+
* @test
38+
*/
39+
public function it_uses_strategy_predefined_when_configured()
40+
{
41+
$this->container->setParameter('kernel.bundles', ['SimpleBusCommandBusBundle'=>true, 'SimpleBusEventBusBundle'=>true]);
42+
$this->load(['events'=>['strategy'=>'predefined']]);
43+
44+
$this->assertContainerBuilderHasServiceDefinitionWithTag('simple_bus.asynchronous.publishes_predefined_messages_middleware', 'event_bus_middleware', ['priority'=>0]);
45+
}
46+
47+
/**
48+
* @test
49+
* @expectedException \LogicException
50+
* @expectedExceptionMessageRegExp ".*SimpleBusCommandBusBundle.*"
51+
*/
52+
public function it_throws_exception_if_command_bus_bundle_is_missing()
53+
{
54+
$this->container->setParameter('kernel.bundles', ['SimpleBusEventBusBundle'=>true]);
55+
$this->load(['events'=>['strategy'=>'predefined']]);
56+
}
57+
58+
/**
59+
* @test
60+
* @expectedException \LogicException
61+
* @expectedExceptionMessageRegExp ".*SimpleBusEventBusBundle.*"
62+
*/
63+
public function it_throws_exception_if_event_bus_bundle_is_missing()
64+
{
65+
$this->container->setParameter('kernel.bundles', ['SimpleBusCommandBusBundle'=>true]);
66+
$this->load(['events'=>['strategy'=>'predefined']]);
67+
}
68+
}

0 commit comments

Comments
 (0)