Thanks to visit codestin.com
Credit goes to github.com

Skip to content

- #23650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

- #23650

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class AsyncEventDispatcher extends EventDispatcher
{
/**
* @var EventDispatcherInterface
*/
private $trueEventDispatcher;

/**
* @var AsyncListener
*/
private $asyncListener;

/**
* @param EventDispatcherInterface $trueEventDispatcher
* @param AsyncListener $asyncListener
*/
public function __construct(EventDispatcherInterface $trueEventDispatcher, AsyncListener $asyncListener)
{
$this->trueEventDispatcher = $trueEventDispatcher;
$this->asyncListener = $asyncListener;
}

/**
* This method dispatches only those listeners that were marked as async.
*
* @param string $eventName
* @param Event|null $event
*/
public function dispatchAsyncListenersOnly($eventName, Event $event = null)
{
try {
$this->asyncListener->syncMode($eventName);

parent::dispatch($eventName, $event);
} finally {
$this->asyncListener->resetSyncMode();
}
}

/**
* {@inheritdoc}
*/
public function dispatch($eventName, Event $event = null)
{
parent::dispatch($eventName, $event);

$this->trueEventDispatcher->dispatch($eventName, $event);
}
}
87 changes: 87 additions & 0 deletions src/Symfony/Component/EventDispatcher/Async/AsyncListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Interop\Queue\PsrContext;
use Interop\Queue\PsrQueue;
use Symfony\Component\EventDispatcher\Event;

class AsyncListener
{
/**
* @var PsrContext
*/
private $context;

/**
* @var Registry
*/
private $registry;

/**
* @var PsrQueue
*/
private $eventQueue;

/**
* @var bool
*/
private $syncMode;

/**
* @param PsrContext $context
* @param Registry $registry
* @param PsrQueue|string $eventQueue
*/
public function __construct(PsrContext $context, Registry $registry, $eventQueue)
{
$this->context = $context;
$this->registry = $registry;
$this->eventQueue = $eventQueue instanceof PsrQueue ? $eventQueue : $context->createQueue($eventQueue);
}

public function __invoke(Event $event, $eventName)
{
$this->onEvent($event, $eventName);
}

public function resetSyncMode()
{
$this->syncMode = [];
}

/**
* @param string $eventName
*/
public function syncMode($eventName)
{
$this->syncMode[$eventName] = true;
}

/**
* @param string $eventName
*
* @return bool
*/
public function isSyncMode($eventName)
{
return isset($this->syncMode[$eventName]);
}

/**
* @param Event $event
* @param string $eventName
*/
public function onEvent(Event $event, $eventName)
{
if (false == isset($this->syncMode[$eventName])) {
$transformerName = $this->registry->getTransformerNameForEvent($eventName);

$message = $this->registry->getTransformer($transformerName)->toMessage($eventName, $event);
$message->setProperty('event_name', $eventName);
$message->setProperty('transformer_name', $transformerName);

$this->context->createProducer()->send($this->eventQueue, $message);
}
}
}
50 changes: 50 additions & 0 deletions src/Symfony/Component/EventDispatcher/Async/AsyncProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Interop\Queue\PsrContext;
use Interop\Queue\PsrMessage;
use Interop\Queue\PsrProcessor;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class AsyncProcessor implements PsrProcessor
{
/**
* @var Registry
*/
private $registry;

/**
* @var AsyncEventDispatcher
*/
private $dispatcher;

/**
* @param Registry $registry
* @param AsyncEventDispatcher $dispatcher
*/
public function __construct(Registry $registry, AsyncEventDispatcher $dispatcher)
{
$this->registry = $registry;
$this->dispatcher = $dispatcher;
}

/**
* {@inheritdoc}
*/
public function process(PsrMessage $message, PsrContext $context)
{
if (false == $eventName = $message->getProperty('event_name')) {
return self::REJECT;
}
if (false == $transformerName = $message->getProperty('transformer_name')) {
return self::REJECT;
}

$event = $this->registry->getTransformer($transformerName)->toEvent($eventName, $message);

$this->dispatcher->dispatchAsyncListenersOnly($eventName, $event);

return self::ACK;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

class ContainerAwareRegistry implements Registry, ContainerAwareInterface
{
use ContainerAwareTrait;

/**
* @var string[]
*/
private $eventsMap;

/**
* @var string[]
*/
private $transformersMap;

/**
* @param string[] $eventsMap [eventName => transformerName]
* @param string[] $transformersMap [transformerName => transformerServiceId]
*/
public function __construct(array $eventsMap, array $transformersMap)
{
$this->eventsMap = $eventsMap;
$this->transformersMap = $transformersMap;
}

/**
* {@inheritdoc}
*/
public function getTransformerNameForEvent($eventName)
{
$transformerName = null;
if (array_key_exists($eventName, $this->eventsMap)) {
$transformerName = $this->eventsMap[$eventName];
} else {
foreach ($this->eventsMap as $eventNamePattern => $name) {
if ('/' != $eventNamePattern[0]) {
continue;
}

if (preg_match($eventNamePattern, $eventName)) {
$transformerName = $name;

break;
}
}
}

if (empty($transformerName)) {
throw new \LogicException(sprintf('There is no transformer registered for the given event %s', $eventName));
}

return $transformerName;
}

/**
* {@inheritdoc}
*/
public function getTransformer($name)
{
if (false == array_key_exists($name, $this->transformersMap)) {
throw new \LogicException(sprintf('There is no transformer named %s', $name));
}

$transformer = $this->container->get($this->transformersMap[$name]);

if (false == $transformer instanceof EventTransformer) {
throw new \LogicException(sprintf(
'The container must return instance of %s but got %s',
EventTransformer::class,
is_object($transformer) ? get_class($transformer) : gettype($transformer)
));
}

return $transformer;
}
}
29 changes: 29 additions & 0 deletions src/Symfony/Component/EventDispatcher/Async/EventTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Interop\Queue\PsrMessage;
use Symfony\Component\EventDispatcher\Event;

interface EventTransformer
{
/**
* @param string $eventName
* @param Event|null $event
*
* @return PsrMessage
*/
public function toMessage($eventName, Event $event);

/**
* If you able to transform message back to event return it.
* If you failed to transform for some reason you can return a string status (@see PsrProcess constants) or an object that implements __toString method.
* The object must have a __toString method is supposed to be used as PsrProcessor::process return value.
*
* @param string $eventName
* @param PsrMessage $message
*
* @return Event|string|object
*/
public function toEvent($eventName, PsrMessage $message);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

use Interop\Queue\PsrContext;
use Interop\Queue\PsrMessage;
use Symfony\Component\EventDispatcher\Event;

class PhpSerializerEventTransformer implements EventTransformer
{
/**
* @var PsrContext
*/
private $context;

/**
* @param PsrContext $context
*/
public function __construct(PsrContext $context)
{
$this->context = $context;
}

/**
* {@inheritdoc}
*/
public function toMessage($eventName, Event $event = null)
{
return $this->context->createMessage(serialize($event));
}

/**
* {@inheritdoc}
*/
public function toEvent($eventName, PsrMessage $message)
{
return unserialize($message->getBody());
}
}
20 changes: 20 additions & 0 deletions src/Symfony/Component/EventDispatcher/Async/Registry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Symfony\Component\EventDispatcher\Async;

interface Registry
{
/**
* @param string $eventName
*
* @return string
*/
public function getTransformerNameForEvent($eventName);

/**
* @param string $name
*
* @return EventTransformer
*/
public function getTransformer($name);
}
Loading