lmc/cqrs-types

包含用于查询和命令的类型(接口和值对象)的库,有助于处理查询和命令

3.2.0 2024-03-06 12:41 UTC

This package is auto-updated.

Last update: 2024-09-06 13:45:09 UTC


README

cqrs-types Latest Stable Version Tests and linting Coverage Status

这个库包含CQRS库的类型(值对象、接口和基本实现)。因此,任何人都可以轻松地为它编写扩展。

目录

安装

composer require lmc/cqrs-types

接口(类型)

这里有许多接口和类型,这些在 其他CQRS库 中实现

查询接口

所有查询的主要接口。查询是一个获取数据而不更改任何内容的请求。它负责声明和创建一个请求,该请求将由 QueryHandlerInterface 处理。实现查询接口的对象可以实施 功能,并且应由一个 QueryFetcher 处理。

可用的特性

  • 缓存
  • 性能分析

查询检索器接口

查询检索器的接口(见 处理器/查询检索器)。

它负责

  • 根据查询请求类型查找查询处理器
  • 处理所有查询特性
    • 缓存
      • 需要 Psr\Cache\CacheItemPoolInterface 的一个实例
    • 性能分析
      • 需要 Lmc\Cqrs\Handler\ProfilerBag 的一个实例
  • 解码来自查询处理器的响应

查询处理器接口

它负责处理特定的查询请求并将结果传递给 OnSuccess 回调。它必须声明它支持哪些请求,并且它不能处理不同的请求。当传递不支持的处理方法请求时,它必须在 OnError 回调中传递 UnsupportedRequestException。它不能抛出任何异常,所有异常都必须传递到 OnError 回调。

如果需要,它可以准备一个查询(例如注入客户端)——但 prepare 方法不应更改查询类型或其内容。它应该仅准备支持的查询。它也不应抛出任何异常。

命令接口

所有命令的主要接口。命令是一个更改数据并可能返回结果数据的请求。它负责声明和创建一个请求,该请求将由 SendCommandHandlerInterface 处理。实现命令接口的对象可以实施 功能,并且应由一个 CommandSender 处理。

可用的特性

  • 性能分析

命令发送者接口

命令发送者的接口(见 处理器/命令发送者)。

它负责

  • 根据命令请求类型查找发送命令处理器
  • 处理所有命令特性
    • 性能分析
      • 需要 Lmc\Cqrs\Handler\ProfilerBag 的一个实例
  • 解码来自发送命令处理器的响应

发送命令处理器接口

负责处理特定的命令请求,并将结果传递给 OnSuccess 回调。它必须声明支持哪些请求,并且不能处理不同的请求。当将不支持请求传递给处理方法时,它必须将 UnsupportedRequestException 传递给 OnError 回调。它不能抛出任何异常,所有异常都必须传递给 OnError 回调。

如果需要,它可以准备一个命令(例如注入客户端)——但是 prepare 方法不应改变命令类型或其内容。它应该只准备支持的命令。它也不能抛出任何异常。

响应解码器接口

用于解码响应(无论是 QueryHandlerInterface 还是 SendCommandHandlerInterface 的结果)。解码器本身应该尽可能小,并且只支持一种解码类型。解码器应按优先级逐个使用(默认实现就是这样)。

如果您需要一个解码器是 final 且不进行其他解码,您必须返回一个 DecodedValue 对象。

  • QueryFetcher 和 CommandSender 负责不将 DecodedValue 发送到任何其他解码器

它应该是纯的。

响应应该以相同的方式解码,在这种情况下,可以安全地将其缓存。

如果您需要在解码器中执行一些不纯的操作,请改用 ImpureResponseDecoderInterface。它与纯解码器工作方式完全相同,但额外的 QueryFetcher 知道解码过程不是纯的,因此它可以做一些额外的事情。例如,QueryFetcher 应在第一次不纯解码之前缓存结果,以免缓存错误的结果。

如果将不支持响应传递给解码方法,则应返回它未改变。它不能抛出异常。

还有一个预定义的响应解码器,用于将 json 字符串解码为数组 —— JsonResponseDecoder

分析器格式化器接口

当命令或查询实现 Feature\ProfileableInterface 时,QueryFetcher/CommandSender 将创建一个包含一些信息的 ProfilerItem。该 ProfilerItem 包含有关持续时间、请求类型、响应、错误等原始数据,并旨在在 Symfony 分析器中显示(如果您使用了一个 CQRS 扩展包)。分析器格式化器将这些项目格式化,以提供比原始数据更好的体验,而原始数据可能难以阅读或不可读。它负责将 ProfilerItem 格式化为另一个 ProfilerItem,以便可以获取/设置所有 ProfilerItem 属性。

有一个 FormattedValue 值对象,用于帮助格式化,它可以传递给大多数 ProfilerItem 属性作为值。它包含原始值和格式化值。

分析器格式化器甚至可以进一步格式化已格式化的 FormattedValue。应按优先级逐个调用多个格式化器对 ProfilerItem 进行格式化,以创建最可读的 ProfilerItem 形式。

还有一个预定义的分析器格式化器,用于将 json 字符串格式化(解码)为数组 —— JsonProfilerFormatter

特性

可缓存接口

它允许将实现此接口的对象存储和加载到 Psr\Cache\CacheItemPoolInterface。它使用一个尽可能唯一的 CacheKey

注意:还需要设置 Psr\Cache\CacheItemPoolInterface 实现到 QueryFetcher

可分析接口

它允许对实现此接口的对象进行分析。 ProfilerId 是一个字符串,它不必是唯一的。

基本实现

基本实现提供了一种(些)方法,这些方法在实现处理器等时通常会被需要。

处理器

AbstractQueryHandlerAbstractSendCommandHandler

为处理方法提供的给定命令/查询的基类实现,以及基类 prepare 方法,后者不对查询/命令进行任何操作(因为大多数处理器不需要它)。

其使用方法如下

class MyQueryHandler extends AbstractQueryHandler
{
    public function supports(QueryInterface $query): bool
    {
        return $query->getRequestType() === ExpectedRequestClass::class;
    }

    public function handle(QueryInterface $query, OnSuccessInterface $onSuccess, OnErrorInterface $onError): void
    {
        if (!$this->assertIsSupported(ExpectedRequestClass::class, $query, $onError)) {
            return;
        }

        try {
            $response = ...;    // handle query/command ...
            $onSuccess($response);
        } catch (\Throwable $e) {
            $onError($e);
        }
    }
}

解码器

CallbackResponseDecoder

如果您需要一种快速解码响应的方法,可以使用此回调响应解码器,该解码器允许您传递一个用于解码的函数。

$decoder = new CallbackResponseDecoder(
    fn (string $response, $initiator) => is_string($response),
    fn (string $response) => sprintf('decoded:%s', $response),
);

JsonResponseDecoder

它将包含json的字符串解码成解码数组。

其他CQRS库