Skip to content

Commit 07bed6e

Browse files
authored
Merge pull request #129 from php-enqueue/bundle-do-not-use-container-aware-event-dispatcher
[bundle] Extend EventDispatcher instead of container aware one.
2 parents 7ba3b09 + 2212dec commit 07bed6e

File tree

55 files changed

+1296
-372
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1296
-372
lines changed

Diff for: .travis.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ install:
5555

5656
script:
5757
# misssing pkg/amqp-ext pkg/job-queue pkg/redis
58-
- if [ "$PHPSTAN" = true ]; then ./bin/phpstan analyse -l 1 -c phpstan.neon pkg/enqueue pkg/psr-queue pkg/fs pkg/simple-client; fi
59-
- if [ "$PHPSTAN" = true ]; then ./bin/phpstan analyse -l 1 -c phpstan.neon pkg/stomp pkg/dbal pkg/enqueue-bundle pkg/null pkg/sqs pkg/test; fi
58+
- if [ "$PHPSTAN" = true ]; then php -d memory_limit=512M bin/phpstan analyse -l 1 -c phpstan.neon pkg/amqp-ext pkg/async-event-dispatcher pkg/dbal pkg/enqueue pkg/enqueue-bundle pkg/fs pkg/gearman pkg/job-queue pkg/null pkg/pheanstalk pkg/psr-queue pkg/redis pkg/simple-client pkg/sqs pkg/stomp pkg/test; fi
6059
- if [ "$PHP_CS_FIXER" = true ]; then IFS=$'\n'; COMMIT_SCA_FILES=($(git diff --name-only --diff-filter=ACMRTUXB "${TRAVIS_COMMIT_RANGE}")); unset IFS; fi
6160
- if [ "$PHP_CS_FIXER" = true ]; then ./bin/php-cs-fixer fix --config=.php_cs.dist -v --dry-run --stop-on-violation --using-cache=no --path-mode=intersection -- "${COMMIT_SCA_FILES[@]}"; fi
6261
- if [ "$UNIT_TESTS" = true ]; then bin/phpunit --exclude-group=functional; fi

Diff for: composer.json

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"enqueue/job-queue": "*@dev",
2020
"enqueue/simple-client": "*@dev",
2121
"enqueue/test": "*@dev",
22+
"enqueue/async-event-dispatcher": "*@dev",
2223

2324
"phpunit/phpunit": "^5",
2425
"doctrine/doctrine-bundle": "~1.2",
@@ -98,6 +99,10 @@
9899
{
99100
"type": "path",
100101
"url": "pkg/simple-client"
102+
},
103+
{
104+
"type": "path",
105+
"url": "pkg/async-event-dispatcher"
101106
}
102107
]
103108
}

Diff for: docs/async_event_dispatcher/quick_tour.md

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Async event dispatcher (Symfony)
2+
3+
The doc shows how you can setup async event dispatching in plain PHP.
4+
If you are looking for the ways to use it in Symfony application [read this post instead](../bundle/async_events.md)
5+
6+
* [Installation](#installation)
7+
* [Configuration](#configuration)
8+
* [Dispatch event](#dispatch-event)
9+
* [Process async events](#process-async-events)
10+
11+
## Installation
12+
13+
You need the async dispatcher library and a one of [the supported transports](../transport)
14+
15+
```bash
16+
$ composer require enqueue/async-event-dispatcher enqueue/fs
17+
```
18+
19+
## Configuration
20+
21+
```php
22+
<?php
23+
24+
// config.php
25+
26+
use Enqueue\AsyncEventDispatcher\AsyncListener;
27+
use Enqueue\AsyncEventDispatcher\AsyncProcessor;
28+
use Enqueue\AsyncEventDispatcher\PhpSerializerEventTransformer;
29+
use Enqueue\AsyncEventDispatcher\AsyncEventDispatcher;
30+
use Enqueue\AsyncEventDispatcher\SimpleRegistry;
31+
use Enqueue\Fs\FsConnectionFactory;
32+
use Symfony\Component\EventDispatcher\EventDispatcher;
33+
34+
require_once __DIR__.'/vendor/autoload.php';
35+
36+
// it could be any other enqueue/psr-queue compatible context.
37+
$context = (new FsConnectionFactory('file://'.__DIR__.'/queues'))->createContext();
38+
$eventQueue = $context->createQueue('symfony_events');
39+
40+
$registry = new SimpleRegistry(
41+
['the_event' => 'default'],
42+
['default' => new PhpSerializerEventTransformer($context, true)]
43+
);
44+
45+
$asyncListener = new AsyncListener($context, $registry, $eventQueue);
46+
47+
$dispatcher = new EventDispatcher();
48+
49+
// the listener sends even as a message through MQ
50+
$dispatcher->addListener('the_event', $asyncListener);
51+
52+
$asyncDispatcher = new AsyncEventDispatcher($dispatcher, $asyncListener);
53+
54+
// the listener is executed on consumer side.
55+
$asyncDispatcher->addListener('the_event', function() {
56+
});
57+
58+
$asyncProcessor = new AsyncProcessor($registry, $asyncDispatcher);
59+
```
60+
61+
## Dispatch event
62+
63+
```php
64+
<?php
65+
66+
// send.php
67+
68+
use Symfony\Component\EventDispatcher\GenericEvent;
69+
70+
require_once __DIR__.'/vendor/autoload.php';
71+
72+
include __DIR__.'/config.php';
73+
74+
$dispatcher->dispatch('the_event', new GenericEvent('theSubject'));
75+
```
76+
77+
## Process async events
78+
79+
```php
80+
<?php
81+
82+
// consume.php
83+
84+
use Enqueue\Psr\PsrProcessor;
85+
86+
require_once __DIR__.'/vendor/autoload.php';
87+
include __DIR__.'/config.php';
88+
89+
$consumer = $context->createConsumer($eventQueue);
90+
91+
while (true) {
92+
if ($message = $consumer->receive(5000)) {
93+
$result = $asyncProcessor->process($message, $context);
94+
95+
switch ((string) $result) {
96+
case PsrProcessor::ACK:
97+
$consumer->acknowledge($message);
98+
break;
99+
case PsrProcessor::REJECT:
100+
$consumer->reject($message);
101+
break;
102+
case PsrProcessor::REQUEUE:
103+
$consumer->reject($message, true);
104+
break;
105+
default:
106+
throw new \LogicException('Result is not supported');
107+
}
108+
}
109+
}
110+
```
111+
112+
[back to index](../index.md)

Diff for: docs/bundle/async_events.md

+4-53
Original file line numberDiff line numberDiff line change
@@ -66,67 +66,18 @@ You can also add an async listener directly and register a custom message proces
6666
6767
services:
6868
acme.async_foo_listener:
69-
class: 'Enqueue\Bundle\Events\AsyncListener'
69+
class: 'Enqueue\AsyncEventDispatcher\AsyncListener'
7070
public: false
71-
arguments: ['@enqueue.client.producer', '@enqueue.events.registry']
71+
arguments: ['@enqueue.transport.default.context', '@enqueue.events.registry', 'a_queue_name']
7272
tags:
7373
- { name: 'kernel.event_listener', event: 'foo', method: 'onEvent' }
7474
```
7575

76-
The message processor must subscribe to `event.foo` topic. The message queue topics names for event follow this patter `event.{eventName}`.
77-
78-
```php
79-
<?php
80-
81-
use Enqueue\Bundle\Events\Registry;
82-
use Enqueue\Client\TopicSubscriberInterface;
83-
use Enqueue\Psr\PsrContext;
84-
use Enqueue\Psr\PsrMessage;
85-
use Enqueue\Psr\PsrProcessor;
86-
87-
class FooEventProcessor implements PsrProcessor, TopicSubscriberInterface
88-
{
89-
/**
90-
* @var Registry
91-
*/
92-
private $registry;
93-
94-
/**
95-
* @param Registry $registry
96-
*/
97-
public function __construct(Registry $registry)
98-
{
99-
$this->registry = $registry;
100-
}
101-
102-
public function process(PsrMessage $message, PsrContext $context)
103-
{
104-
if (false == $eventName = $message->getProperty('event_name')) {
105-
return self::REJECT;
106-
}
107-
if (false == $transformerName = $message->getProperty('transformer_name')) {
108-
return self::REJECT;
109-
}
110-
111-
// do what you want with the event.
112-
$event = $this->registry->getTransformer($transformerName)->toEvent($eventName, $message);
113-
114-
115-
return self::ACK;
116-
}
117-
118-
public static function getSubscribedTopics()
119-
{
120-
return ['event.foo'];
121-
}
122-
}
123-
```
124-
12576

12677
## Event transformer
12778

12879
The bundle uses [php serializer](https://github.com/php-enqueue/enqueue-dev/blob/master/pkg/enqueue-bundle/Events/PhpSerializerEventTransformer.php) transformer by default to pass events through MQ.
129-
You could create a transformer for the given event type. The transformer must implement `Enqueue\Bundle\Events\EventTransformer` interface.
80+
You could create a transformer for the given event type. The transformer must implement `Enqueue\AsyncEventDispatcher\EventTransformer` interface.
13081
Consider the next example. It shows how to send an event that contains Doctrine entity as a subject
13182

13283
```php
@@ -140,7 +91,7 @@ use Enqueue\Consumption\Result;
14091
use Enqueue\Psr\PsrMessage;
14192
use Enqueue\Util\JSON;
14293
use Symfony\Component\EventDispatcher\Event;
143-
use Enqueue\Bundle\Events\EventTransformer;
94+
use Enqueue\AsyncEventDispatcher\EventTransformer;
14495
use Doctrine\Bundle\DoctrineBundle\Registry;
14596
use Symfony\Component\EventDispatcher\GenericEvent;
14697

Diff for: docs/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
- [Production settings](bundle/production_settings.md)
3535
- [Debuging](bundle/debuging.md)
3636
- [Functional testing](bundle/functional_testing.md)
37+
* Async event dispatcher (Symfony)
38+
- [Quick tour](async_event_dispatcher/quick_tour.md)
3739
* Magento
3840
- [Quick tour](magento/quick_tour.md)
3941
- [Cli commands](magento/cli_commands.md)

Diff for: phpstan.neon

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
parameters:
22
excludes_analyse:
3-
- pkg/enqueue/Util/UUID.php
3+
- pkg/enqueue/Util/UUID.php
4+
- pkg/enqueue-bundle/Tests/Functional/App
5+
- pkg/job-queue/Test/JobRunner.php
6+
- pkg/job-queue/Tests/Functional/app/AppKernel.php
7+
- pkg/redis/PhpRedis.php
8+
- pkg/redis/RedisConnectionFactory.php
9+
- pkg/gearman
10+
- pkg/amqp-ext/AmqpConsumer.php

Diff for: phpunit.xml.dist

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@
6868
<testsuite name="simple-client">
6969
<directory>pkg/simple-client/Tests</directory>
7070
</testsuite>
71+
72+
<testsuite name="async-event-dispatcher">
73+
<directory>pkg/async-event-dispatcher/Tests</directory>
74+
</testsuite>
7175
</testsuites>
7276

7377
<filter>

Diff for: pkg/async-event-dispatcher/.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*~
2+
/composer.lock
3+
/composer.phar
4+
/phpunit.xml
5+
/vendor/
6+
/.idea/
7+
Tests/Functional/queues

Diff for: pkg/async-event-dispatcher/.travis.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
sudo: false
2+
3+
git:
4+
depth: 1
5+
6+
language: php
7+
8+
php:
9+
- '5.6'
10+
- '7.0'
11+
12+
cache:
13+
directories:
14+
- $HOME/.composer/cache
15+
16+
install:
17+
- composer self-update
18+
- composer install --prefer-source --ignore-platform-reqs
19+
20+
script:
21+
- vendor/bin/phpunit --exclude-group=functional

Diff for: pkg/async-event-dispatcher/AsyncEventDispatcher.php

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Enqueue\AsyncEventDispatcher;
4+
5+
use Symfony\Component\EventDispatcher\Event;
6+
use Symfony\Component\EventDispatcher\EventDispatcher;
7+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
8+
9+
class AsyncEventDispatcher extends EventDispatcher
10+
{
11+
/**
12+
* @var EventDispatcherInterface
13+
*/
14+
private $trueEventDispatcher;
15+
16+
/**
17+
* @var AsyncListener
18+
*/
19+
private $asyncListener;
20+
21+
/**
22+
* @param EventDispatcherInterface $trueEventDispatcher
23+
* @param AsyncListener $asyncListener
24+
*/
25+
public function __construct(EventDispatcherInterface $trueEventDispatcher, AsyncListener $asyncListener)
26+
{
27+
$this->trueEventDispatcher = $trueEventDispatcher;
28+
$this->asyncListener = $asyncListener;
29+
}
30+
31+
/**
32+
* This method dispatches only those listeners that were marked as async.
33+
*
34+
* @param string $eventName
35+
* @param Event|null $event
36+
*/
37+
public function dispatchAsyncListenersOnly($eventName, Event $event = null)
38+
{
39+
try {
40+
$this->asyncListener->syncMode($eventName);
41+
42+
parent::dispatch($eventName, $event);
43+
} finally {
44+
$this->asyncListener->resetSyncMode();
45+
}
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function dispatch($eventName, Event $event = null)
52+
{
53+
parent::dispatch($eventName, $event);
54+
55+
$this->trueEventDispatcher->dispatch($eventName, $event);
56+
}
57+
}

0 commit comments

Comments
 (0)