neos/event-sourcing-symfony-bridge 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

neos/event-sourcing-symfony-bridge

Composer 安装命令:

composer require neos/event-sourcing-symfony-bridge

包简介

Symfony bridge to integrate Event Sourcing and CQRS pattern in your Symfony framework.

README 文档

README

Library providing interfaces and implementations for event-sourced applications for Symfony Applications.

This package is the symfony adapter of Neos.EventSourcing (which was created for the Neos/Flow framework).

Demo

Check out the Symfony Demo Repository:

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

Getting started

In your symfony application, install this package and neos/event-sourcing via composer:

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

Setting up a Doctrine Event Store

Since there could be multiple Event Stores simultaneously in one application, this package comes without a pre-configured "default" store. It is just a matter of a couple of lines of YAML to configure a custom store:

config/packages/neos_eventsourcing.yaml:

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

Set the charset in the doctrine config to utf8mb4 by adding the following lines.

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

Add the following to bundles.php:

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

To make use of the newly configured Event Store one more step is required in order to finish the setup (in this case to create the corresponding database table):

php bin/console eventsourcing:store-setup

Writing events

Example event: 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
));

Reading events

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

Reacting to events

In order to react upon new events you'll need an event listener:

<?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)
    {
        
    }

The when*() methods of classes implementing the EventSubscriberInterface and ProjectorInterface will be invoked whenever a corresponding event is committed to the Event Store.

NOTE!!! You always have to use "when*" namings, as otherwise, the EventListenerInvoker will not properly call the right methods here (see neos/Neos.EventSourcing#282)

Replay projection

With the following command you can rebuild a projection.

bin/console eventsourcing:projection-replay eventListenerClassName eventStoreContainerId

Events & event listeners

The Neos EventSourcing package comes with its own events and event listeners implementation. We cannot use this implementation for several reasons in the symfony context.

To get the listeners (subscribers in symfony) for an event we call the symfony event dispatcher (in the SymfonyEventPublisher).

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

The listeners are handled by the InternalCatchUpEventListenerCommand. This command uses the (Neos EventSourcing) EventListenerInvoker to call the listeners method name.

The specialty about this is that the EventSourcing package uses the "when*" namings. For that reason the listeners method names have to start with when* prefix too (@see Reacting to events).

All configuration options in neos_eventsourcing.yml

  • stores
    • [name of event store]
      • eventTableName: database table name to use as event storage (required)
      • storage: which storage engine to use for persisting events. A class name, by default: Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage
      • eventPublisherTransport: Class name. How the asychronity between event store and projection is implemented. By default, Neos\EventSourcing\SymfonyBridge\Transport\ConsoleCommandTransport is used, but also Neos\EventSourcing\SymfonyBridge\Transport\MessengerTransport is possible.

Internal Implementation

How is this package constructed? We try to give an overview here:

composer.json

We replace neos/flow and flowpack/jobqueue-common to ensure these are not installed.

neos/event-sourcing-symfony-bridge 适用场景与选型建议

neos/event-sourcing-symfony-bridge 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5k 次下载、GitHub Stars 达 4, 最近一次更新时间为 2022 年 03 月 28 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 neos/event-sourcing-symfony-bridge 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 neos/event-sourcing-symfony-bridge 我们能提供哪些服务?
定制开发 / 二次开发

基于 neos/event-sourcing-symfony-bridge 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 5k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 4
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 4
  • Watchers: 2
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-03-28