apip-ddd
apip-ddd copied to clipboard
Add async commands
Hi, I am using this repository as base for my new project. However this repo does not implement async commands and as a consequence it does not show how to consider async commands inside a command bus implementation.
I rewritten the MessengerCommandBus implementation however this does not satisfy PHPStan as returning null for async commands results in error
Method MessengerCommandBus::dispatch() should return T but returns null.
💡 Type null is not always the same as T. It breaks the contract for some argument types, typically subtypes.
final class MessengerCommandBus implements CommandBusInterface
{
public function __construct(MessageBusInterface $commandBus)
{
$this->messageBus = $commandBus;
}
/**
* @template T
*
* @param CommandInterface<T> $command
*
* @return T
*/
public function dispatch(CommandInterface $command): mixed
{
try {
$envelope = $this->messageBus->dispatch($message);
/** @var HandledStamp[] $handledStamps */
$handledStamps = $envelope->all(HandledStamp::class);
if (!$handledStamps) {
// async command
return null;
}
if (\count($handledStamps) > 1) {
$handlers = implode(', ', array_map(fn (HandledStamp $stamp): string => sprintf('"%s"', $stamp->getHandlerName()), $handledStamps));
throw new LogicException(sprintf('Message of type "%s" was handled multiple times. Only one handler is expected when using "%s::%s()", got %d: %s.', get_debug_type($envelope->getMessage()), static::class, __FUNCTION__, \count($handledStamps), $handlers));
}
return $handledStamps[0]->getResult();
} catch (HandlerFailedException $e) {
if ($exception = current($e->getWrappedExceptions())) {
throw $exception;
}
throw $e;
}
}
}