neos/event-sourcing-symfony-bridge

Symfony 桥接器,用于在您的 Symfony 框架中集成事件源和 CQRS 模式。

资助包维护!
shop.neos.io/neosfunding

安装次数: 4,996

依赖项: 0

建议者: 0

安全: 0

星标: 4

关注者: 3

分支: 0

开放问题: 1

类型:symfony-bundle

1.1.0 2022-04-02 18:09 UTC

This package is auto-updated.

Last update: 2024-08-30 01:17:59 UTC


README

为 Symfony 应用程序提供事件源应用程序接口和实现的库。

本包是 Neos.EventSourcing(为 Neos/Flow 框架创建)的 Symfony 适配器。

演示

查看 Symfony 演示存储库

https://github.com/Inchie/symfony-eventsourcing-demo.git

入门

在您的 symfony 应用程序中,使用 composer 安装此包和 neos/event-sourcing

composer require neos/event-sourcing-symfony-bridge neos/event-sourcing

设置 Doctrine 事件存储

由于一个应用程序中可能同时存在多个事件存储,因此此包不包含预配置的“默认”存储。只需几行 YAML 配置即可设置自定义存储

config/packages/neos_eventsourcing.yaml

neos_eventsourcing:
  stores:
    'blog.events':
      eventTableName: blog_events
    'user.events':
      eventTableName: user_events

在 doctrine 配置中将字符集设置为 utf8mb4,通过添加以下行。

config/packages/doctrine.yaml

doctrine:
    dbal:
        connections:
            default:
                url: '%env(resolve:DATABASE_URL)%'

                # IMPORTANT: You MUST configure your server version,
                # either here or in the DATABASE_URL env var (see .env file)
                server_version: '5.7'

                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci

将以下内容添加到 bundles.php

Neos\EventSourcing\SymfonyBridge\NeosEventSourcingBundle::class => ['all' => true],

要使用新配置的事件存储,完成设置还需要进行一步操作(在这种情况下是创建相应的数据库表)

php bin/console eventsourcing:store-setup

编写事件

示例事件: BlogWasCreated.php
class BlogWasCreated implements DomainEventInterface
{
    /**
     * @var BlogIdentifier
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * @var UserIdentifier
     */
    private $author;

    public function __construct(
        BlogIdentifier $id,
        string $name,
        UserIdentifier $author
    )
    {
        $this->id = $id;
        $this->name = $name;
        $this->author = $author;
    }

    public function getId(): BlogIdentifier
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getAuthor(): UserIdentifier
    {
        return $this->author;
    }
}
<?php
$uuid = $this->blogRepository->nextIdentity();
$event = new BlogWasCreated(
    $uuid,
    $command->getName(),
    $command->getAuthorIdentifier()
);

$stream = StreamName::fromString('some-stream');
$this->eventStore->commit($stream, DomainEvents::withSingleEvent(
    $event
));

读取事件

<?php
$streamName = StreamName::fromString('some-stream');
$eventStream = $this->eventStore->load($streamName)

对事件做出反应

为了对新事件做出反应,您需要一个事件监听器

<?php
class BlogListProjector implements ProjectorInterface, EventSubscriberInterface
{
    private $blogRepository;

    public function __construct(BlogRepository $blogRepository)
    {
        $this->blogRepository = $blogRepository;
    }

    public static function getSubscribedEvents()
    {
        return [
            // NOTE!!! you always have to use "when*" namings, as otherwise, the EventListenerInvoker
            // will not properly call the right methods here.

            // we only use the EventSubscriber from symfony to figure out which listeners should be called.
            BlogWasCreated::class => ['whenBlogWasCreated']
        ];
    }

    public function whenBlogWasCreated(BlogWasCreated $event, RawEvent $rawEvent)
    {
        
    }

实现 EventSubscriberInterfaceProjectorInterface 的类的 when*() 方法将在相应的事件提交到事件存储时被调用。

注意!!!您必须始终使用 "when*" 命名,否则 EventListenerInvoker 将无法正确调用此处的方法(请参阅 neos/Neos.EventSourcing#282

重放投影

使用以下命令可以重建投影。

bin/console eventsourcing:projection-replay eventListenerClassName eventStoreContainerId

事件和事件监听器

Neos EventSourcing 包附带其自己的事件和事件监听器实现。在 symfony 上下文中,我们无法使用此实现,原因有很多。

要为事件获取监听器(symfony 中的订阅者),我们调用 symfony 事件调度器(在 SymfonyEventPublisher 中)。

$listeners = $this->eventDispatcher->getListeners($eventClassName);

监听器由 InternalCatchUpEventListenerCommand 处理。该命令使用(Neos EventSourcing)EventListenerInvoker 调用监听器方法名称。

关于这一点,特别之处在于 EventSourcing 包使用 "when*" 命名。因此,监听器方法名称也必须以 when* 前缀开头(请参阅对事件做出反应)。

neos_eventsourcing.yml 中的所有配置选项

  • 存储
    • 事件存储的名称
      • eventTableName:用作事件存储的数据库表名称(必需)
      • storage:用于持久化事件的存储引擎。默认为类名:Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage
      • eventPublisherTransport:类名。如何实现事件存储和投影之间的异步性。默认情况下使用 Neos\EventSourcing\SymfonyBridge\Transport\ConsoleCommandTransport,但也可以使用 Neos\EventSourcing\SymfonyBridge\Transport\MessengerTransport

内部实现

这个包是如何构建的?我们在这里尝试提供一个概述。

composer.json

我们将neos/flowflowpack/jobqueue-common替换,以确保它们没有被安装。