Skip to content

Commit

Permalink
Add QueryDispatcher/CommandDispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
olvlvl committed Apr 16, 2018
1 parent 5192cce commit 6231d87
Show file tree
Hide file tree
Showing 19 changed files with 310 additions and 23 deletions.
13 changes: 8 additions & 5 deletions README.md
Expand Up @@ -120,19 +120,22 @@ $handler_provider = new ContainerHandlerProvider([
], $container);
```

If you're using [symfony/dependency-injection][] you can add an instance of [MessageBusPass][]
If you're using [symfony/dependency-injection][] you can add an instance of [HandlerProviderPass][]
to your compilation pass to automatically generate the provider:

```yaml
services:

ICanBoogie\MessageBus\SimpleDispatcher:
autowire: true

ICanBoogie\MessageBus\HandlerProvider:
synthetic: true

handler.article.create:
class: App\Domain\Article\Handler\CreateArticleHandler
tags:
- name: message_bus.handler
- name: message_dispatcher.handler
message: App\Application\Message\CreateArticle
```

Expand All @@ -142,14 +145,14 @@ services:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator;
use ICanBoogie\MessageBus\Symfony\MessageBusPass;
use ICanBoogie\MessageBus\Symfony\HandlerProviderPass;

/* @var string $config */

$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
$loader->load($config);
$container->addCompilerPass(new MessageBusPass);
$container->addCompilerPass(new HandlerProviderPass);
$container->compile();
```

Expand Down Expand Up @@ -255,7 +258,7 @@ The package is continuously tested by [Travis CI](http://about.travis-ci.org/).
[documentation]: https://icanboogie.org/api/message-bus/0.6/
[AssertingDispatcher]: https://icanboogie.org/api/message-bus/0.6/class-ICanBoogie.MessageBus.AssertingDispatcher.html
[HandlerProvider]: https://icanboogie.org/api/message-bus/0.6/class-ICanBoogie.MessageBus.HandlerProvider.html
[MessageBusPass]: https://icanboogie.org/api/message-bus/0.6/class-ICanBoogie.MessageBus.Symfony.MessageBusPass.html
[HandlerProviderPass]: https://icanboogie.org/api/message-bus/0.6/class-ICanBoogie.MessageBus.Symfony.MessageBusPass.html
[PSR\ContainerHandlerProvider]: https://icanboogie.org/api/message-bus/0.6/class-ICanBoogie.MessageBus.PSR.ContainerHandlerProvider.html
[available on GitHub]: https://github.com/ICanBoogie/MessageBus
[icanboogie/service]: https://github.com/ICanBoogie/Service
Expand Down
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -30,6 +30,7 @@
"require-dev": {
"psr/container": "^1.0",
"symfony/dependency-injection": "^4.0",
"symfony/event-dispatcher": "^4.0",
"symfony/config": "^4.0",
"symfony/yaml": "^4.0"
},
Expand Down
13 changes: 13 additions & 0 deletions lib/CommandDispatcher.php
@@ -0,0 +1,13 @@
<?php

namespace ICanBoogie\MessageBus;

interface CommandDispatcher extends Dispatcher
{
/**
* @param object $command
*
* @return mixed
*/
public function dispatch(object $command);
}
2 changes: 1 addition & 1 deletion lib/Exception.php
Expand Up @@ -12,7 +12,7 @@
namespace ICanBoogie\MessageBus;

/**
* CommandBus exceptions implement this interface so that they can be easily recognized.
* Dispatcher exceptions implement this interface so that they can be easily recognized.
*/
interface Exception
{
Expand Down
23 changes: 23 additions & 0 deletions lib/PSR/CommandDispatcher.php
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\PSR;

use ICanBoogie\MessageBus\CommandDispatcher as Contract;
use ICanBoogie\MessageBus\SimpleDispatcher;

class CommandDispatcher extends SimpleDispatcher implements Contract
{
public function __construct(CommandHandlerProvider $handler_provider)
{
parent::__construct($handler_provider);
}
}
17 changes: 17 additions & 0 deletions lib/PSR/CommandHandlerProvider.php
@@ -0,0 +1,17 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\PSR;

class CommandHandlerProvider extends ContainerHandlerProvider
{

}
23 changes: 23 additions & 0 deletions lib/PSR/QueryDispatcher.php
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\PSR;

use ICanBoogie\MessageBus\QueryDispatcher as Contract;
use ICanBoogie\MessageBus\SimpleDispatcher;

class QueryDispatcher extends SimpleDispatcher implements Contract
{
public function __construct(QueryHandlerProvider $handler_provider)
{
parent::__construct($handler_provider);
}
}
17 changes: 17 additions & 0 deletions lib/PSR/QueryHandlerProvider.php
@@ -0,0 +1,17 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\PSR;

class QueryHandlerProvider extends ContainerHandlerProvider
{

}
13 changes: 13 additions & 0 deletions lib/QueryDispatcher.php
@@ -0,0 +1,13 @@
<?php

namespace ICanBoogie\MessageBus;

interface QueryDispatcher extends Dispatcher
{
/**
* @param object $query
*
* @return mixed
*/
public function dispatch(object $query);
}
53 changes: 53 additions & 0 deletions lib/Symfony/CommandHandlerProviderPass.php
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\Symfony;

use ICanBoogie\MessageBus\PSR\CommandHandlerProvider;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CommandHandlerProviderPass extends HandlerProviderPass
{
const DEFAULT_SERVICE_ID = CommandHandlerProvider::class;
const DEFAULT_HANDLER_TAG = 'command_dispatcher.handler';
const DEFAULT_QUERY_PROPERTY = 'command';

/**
* @var string
*/
private $service_id;

public function __construct(
string $service_id = self::DEFAULT_SERVICE_ID,
string $handler_tag = self::DEFAULT_HANDLER_TAG,
string $command_property = self::DEFAULT_QUERY_PROPERTY
) {
$this->service_id = $service_id;

parent::__construct($service_id, $handler_tag, $command_property);
}

/**
* @inheritdoc
*/
public function process(ContainerBuilder $container)
{
[ $mapping, $ref_map ] = $this->collectHandlers($container);

$container
->register($this->service_id, CommandHandlerProvider::class)
->setArguments([
$mapping,
ServiceLocatorTagPass::register($container, $ref_map)
]);
}
}
Expand Up @@ -21,13 +21,13 @@
use Symfony\Component\DependencyInjection\TypedReference;

/**
* Registers command bus handlers.
* Collect message handlers and register their provider.
*/
class MessageBusPass implements CompilerPassInterface
class HandlerProviderPass implements CompilerPassInterface
{
const DEFAULT_SERVICE_ID = HandlerProvider::class;
const DEFAULT_HANDLER_TAG = 'message_bus.handler';
const DEFAULT_MESSAGE_PROPERTY = 'message';
const DEFAULT_HANDLER_TAG = 'message_dispatcher.handler';
const DEFAULT_QUERY_PROPERTY = 'message';

/**
* @var string
Expand All @@ -47,7 +47,7 @@ class MessageBusPass implements CompilerPassInterface
public function __construct(
string $service_id = self::DEFAULT_SERVICE_ID,
string $handler_tag = self::DEFAULT_HANDLER_TAG,
string $message_property = self::DEFAULT_MESSAGE_PROPERTY
string $message_property = self::DEFAULT_QUERY_PROPERTY
) {
$this->service_id = $service_id;
$this->handler_tag = $handler_tag;
Expand All @@ -58,6 +58,18 @@ public function __construct(
* @inheritdoc
*/
public function process(ContainerBuilder $container)
{
[ $mapping, $ref_map ] = $this->collectHandlers($container);

$container
->register($this->service_id, ContainerHandlerProvider::class)
->setArguments([
$mapping,
ServiceLocatorTagPass::register($container, $ref_map)
]);
}

protected function collectHandlers(ContainerBuilder $container): array
{
$handlers = $container->findTaggedServiceIds($this->handler_tag, true);
$message_property = $this->message_property;
Expand Down Expand Up @@ -85,11 +97,6 @@ public function process(ContainerBuilder $container)
$ref_map[$id] = new TypedReference($id, $container->getDefinition($id)->getClass());
}

$container
->register($this->service_id, ContainerHandlerProvider::class)
->setArguments([
$mapping,
ServiceLocatorTagPass::register($container, $ref_map)
]);
return [ $mapping, $ref_map ];
}
}
53 changes: 53 additions & 0 deletions lib/Symfony/QueryHandlerProviderPass.php
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus\Symfony;

use ICanBoogie\MessageBus\PSR\QueryHandlerProvider;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class QueryHandlerProviderPass extends HandlerProviderPass
{
const DEFAULT_SERVICE_ID = QueryHandlerProvider::class;
const DEFAULT_HANDLER_TAG = 'query_dispatcher.handler';
const DEFAULT_QUERY_PROPERTY = 'query';

/**
* @var string
*/
private $service_id;

public function __construct(
string $service_id = self::DEFAULT_SERVICE_ID,
string $handler_tag = self::DEFAULT_HANDLER_TAG,
string $query_property = self::DEFAULT_QUERY_PROPERTY
) {
$this->service_id = $service_id;

parent::__construct($service_id, $handler_tag, $query_property);
}

/**
* @inheritdoc
*/
public function process(ContainerBuilder $container)
{
[ $mapping, $ref_map ] = $this->collectHandlers($container);

$container
->register($this->service_id, QueryHandlerProvider::class)
->setArguments([
$mapping,
ServiceLocatorTagPass::register($container, $ref_map)
]);
}
}
8 changes: 8 additions & 0 deletions tests/Symfony/CommandA.php
@@ -0,0 +1,8 @@
<?php

namespace ICanBoogie\MessageBus\Symfony;

class CommandA
{

}
20 changes: 19 additions & 1 deletion tests/Symfony/MessageBusPassTest.php
Expand Up @@ -16,7 +16,9 @@
use ICanBoogie\MessageBus\HandlerProvider;
use ICanBoogie\MessageBus\MessageA;
use ICanBoogie\MessageBus\MessageB;
use ICanBoogie\MessageBus\PSR\CommandDispatcher;
use ICanBoogie\MessageBus\PSR\ContainerHandlerProvider;
use ICanBoogie\MessageBus\PSR\QueryDispatcher;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyContainerBuilder;
Expand Down Expand Up @@ -54,12 +56,28 @@ public function test_should_return_handler()
$this->assertInstanceOf(HandlerB::class, $provider(new MessageB()));
}

public function test_cqs()
{
$container = new SymfonyContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
$loader->load(__DIR__ . '/resources/cqs.yml');
$container
->addCompilerPass(new QueryHandlerProviderPass)
->addCompilerPass(new CommandHandlerProviderPass)
->compile();

$command_dispatcher = $container->get('command_dispatcher');
$query_dispatcher = $container->get('query_dispatcher');
$this->assertInstanceOf(CommandDispatcher::class, $command_dispatcher);
$this->assertInstanceOf(QueryDispatcher::class, $query_dispatcher);
}

private function makeContainer(string $config, string $alias = null): SymfonyContainerBuilder
{
$container = new SymfonyContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
$loader->load($config);
$container->addCompilerPass(new MessageBusPass);
$container->addCompilerPass(new HandlerProviderPass);

if ($alias)
{
Expand Down

0 comments on commit 6231d87

Please sign in to comment.