phpgears/cqrs-async

0.3.1 2019-10-05 11:20 UTC

This package is auto-updated.

Last update: 2024-08-25 05:25:50 UTC


README

PHP version Latest Version License

Build Status Style Check Code Quality Code Coverage

Total Downloads Monthly Downloads

异步CQRS

CQRS命令总线异步装饰器

安装

Composer

composer require phpgears/cqrs-async

使用

需要composer自动加载文件

require './vendor/autoload.php';

异步命令总线

异步处理命令的命令总线装饰器

入队

use Gears\CQRS\Async\AsyncCommandBus;
use Gears\CQRS\Async\Serializer\JsonCommandSerializer;
use Gears\CQRS\Async\Discriminator\ParameterCommandDiscriminator;

/* @var \Gears\CQRS\CommandBus $commandBus */

/* @var Gears\CQRS\Async\CommandQueue $commandQueue */
$commandQueue = new CustomCommandQueue(new JsonCommandSerializer());

$asyncCommandBus new AsyncCommandBus(
    $commandBus,
    $commandQueue,
    new ParameterCommandDiscriminator('async')
);

$asyncCommand = new CustomCommand(['async' => true]);

$asyncCommandBus->handle($asyncCommand);

出队

这部分高度依赖于您的消息队列,尽管可以使用命令序列化器来反序列化队列消息

这只是一个流程示例

use Gears\CQRS\Async\ReceivedCommand;
use Gears\CQRS\Async\Serializer\JsonCommandSerializer;

/* @var \Gears\CQRS\Async\AsyncCommandBus $asyncCommandBus */
/* @var your_message_queue_manager $queue */

$serializer = new JsonCommandSerializer();

while (true) {
  $message = $queue->getMessage();

  if ($message !== null) {
    $command = new ReceivedCommand($serializer->fromSerialized($message));

    $asyncCommandBus->handle($command);
  }
}

为了防止无限循环,应该将反序列化的命令包装在 Gears\CQRS\Async\ReceivedCommand 中,如果您决定将命令处理到异步命令总线。如果您决定在出队侧使用非异步总线,则不需要这样做

判别器

根据任意条件判断命令是否应该入队

此包提供了三个判别器

  • Gears\CQRS\Async\Discriminator\ArrayCommandDiscriminator 如果命令存在于提供的数组中,则选择命令
  • Gears\CQRS\Async\Discriminator\ClassCommandDiscriminator 通过它们的类或接口选择命令
  • Gears\CQRS\Async\Discriminator\ParameterCommandDiscriminator 通过命令负载参数的存在(可选地通过其值)选择命令

命令队列

这部分负责实际的异步处理,通常会将序列化的命令发送到消息队列系统,如RabbitMQ

不提供实现,只提供一个抽象基类,因此您可以从中扩展

use Gears\CQRS\Async\AbstractCommandQueue;

class CustomCommandQueue extends AbstractCommandQueue
{
  public function send(Command $command): void
  {
    // Do the actual enqueue of $this->getSerializedCommand($command);
  }
}

您可以使用 cqrs-async-queue-interop,该工具使用 queue-interop 进行消息入队

序列化器

抽象命令队列使用序列化器进行命令序列化,以便将其作为字符串消息发送到消息队列

Gears\CQRS\Async\Serializer\JsonCommandSerializer 直接提供作为通用序列化器,以在命令由其他系统处理时提供最大兼容性

如果您提供的序列化器不符合您的需求,可以创建自己的序列化器,例如使用 JMS serializer,通过实现 Gears\CQRS\Async\Serializer\CommandSerializer 接口

分布式系统

在分布式系统上,例如微服务系统,命令可以在系统的完全不同部分进行出队,这部分当然应该了解命令及其内容,但最终可能无法访问命令类本身

例如,在DDD的域事件上下文中,一个边界上下文可以处理由另一个完全不同的边界上下文传递的命令,当然无法反序列化原始命令,因为它位于另一个域

可以通过两种方式解决这个问题,在将消息传递给命令序列化器之前在消息队列中转换消息,或者更好地创建一个自定义的 Gears\CQRS\Async\Serializer\CommandSerializer 来封装这种转换

转换可能只是更改要重构的命令类

贡献

发现了一个错误或有一个功能请求? 请打开一个新的问题。在提出请求之前先查看现有的问题。

请参阅文件 CONTRIBUTING.md

许可证

请参阅源代码中包含的文件 LICENSE 中的许可证条款副本。