markkimsal / laravel-event-sourcing
在 Laravel 中开始使用事件源的最简单方法
Requires
- php: ^7.2|^8.0
- ext-json: *
- illuminate/console: ^6.0|^7.0|^8.0
- illuminate/database: ^6.0|^7.30.4|^8.0
- illuminate/events: ^6.0|^7.0|^8.0
- illuminate/support: ^6.0|^7.0|^8.0
- league/flysystem: ^1.0.45
- spatie/laravel-schemaless-attributes: ^1.6
- symfony/finder: ^4.2|^5.0
- symfony/property-access: ^4.0|^5.0
- symfony/serializer: ^4.0|^5.0
Requires (Dev)
- mockery/mockery: ^1.3
- orchestra/testbench: ^4.0|^5.0|^6.0
- phpunit/phpunit: ^8.4|^9.5
- spatie/phpunit-snapshot-assertions: ^2.1|^3.1|^4.1
README
我还没有找到一款能够正确处理并发性的 PHP 事件源库,所以我修复了一个。
从 spatie 分支修复
- 不允许对同一聚合根 UUID 的事件流进行并发更新
- 修复并发读取 - (锁定读取(修复主键“间隙”))
- 修复并发写入 - (将 aggregateVersion 按事件而不是按持久化进行划分)
其他更改
- 删除短函数()语法(PHP 7.3)
- 删除成员变量类型(PHP 7.3)
- AggregateRoot uuid 是受保护的而不是私有的
- 静态 make() 类似于 retrieve 但不进行数据库查找
锁定和事务
MySQL 的 SELECT ... LOCK IN SHARE MODE
在事务内或外(autocommit=1)执行时表现不同。
使用锁定读取将尝试获取间隙锁或下一个键锁,因为我们正在扫描非唯一索引 'aggregate_uuid'(但我相信即使有 'aggregate_uuid' 和 'aggregate_version' 的复合唯一键也会发生这种情况)。尝试在 autocommit=1 和 BEGIN
或 START TRANSACTION
语句之外获取锁将导致等待其他插入已获取下一个键锁以完成并刷新输出。这意味着选择 pkeys 的范围不会导致“间隙”。
在事务内使用锁定读取将尝试获取任何扫描的行的相同锁,并获取任何扫描的索引中下一个要插入的项目上的锁。因此,在事务内使用锁定读取将阻止向 stored_events
表中插入任何内容,因为锁在 'aggregate_uuid' 的下一个最高值上,有效地阻止了所有插入。
在我们找到最高 aggregate_version 并插入新事件之前,我们不在事务内使用锁定读取,但这种想法已被尝试,所以一些函数注释可能引用了这种方法。
所有这些假设都是 ISOLATION LEVEL READ COMMITTED(这是 MySQL 的默认值)。
对于所有 retrieve()
调用,其目的是重新构成聚合,我们使用锁定读取以确保我们看到任何正在进行的写事务的一致视图。
对于任何尝试确保内存中聚合的 'aggregate_version' 参数与内存中的聚合参数最新的预插入读取,我们不使用锁定读取,并依赖于 'aggregate_uuid' + 'aggregate_version' 的唯一索引来防止过时的写入。
任何对 persist()
的调用都可能抛出 CouldNotPersistAggregate
异常。
静态 Make
当你子类化 AggregateRoot 时,你始终必须进行 retrieve($uuid)
调用来设置 UUID。不可能设置 UUID 并跳过任何事件加载。
//spatie way
$order = OrderAggregate::retrieve($uuid);
//my way
$order = OrderAggregate::make($uuid);
原始 README
此包旨在成为开始使用 Laravel 事件源的人口点。它可以帮助你设置聚合、投影器和反应器。
如果你从未使用过事件源,或者不确定聚合、投影器和反应器是什么,请访问我们的文档中的“熟悉事件源”部分 (我们的文档)。
如果以下情况适用,事件源可能是你的项目的最佳选择:
- 你的应用程序需要根据过去做出决策
- 您的应用程序有审计要求:应用程序处于某种状态的原因与状态本身同样重要。
- 您预见将来会有报告需求,但目前尚不清楚需要收集哪些数据。
如果您想立即阅读代码,这里有一些示例应用程序。在它们中,您可以创建账户并存入或取出资金。
支持我们
我们投入了大量资源来创建业界最佳开源软件包。您可以通过购买我们的付费产品之一来支持我们。
我们非常感激您从家乡寄给我们明信片,并提及您正在使用我们哪个软件包。您可以在我们的联系页面找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上。
文档
您可以在专门的文档网站找到安装说明和如何使用此软件包的详细说明。
从 laravel-event-projector 升级
此软件包取代了laravel-event-projector。它具有相同的API。从 laravel-event-projector 升级到 laravel-event-sourcing 很简单。请参阅我们的升级指南。
变更日志
请参阅CHANGELOG以获取更多关于最近更改的信息。
贡献
请参阅CONTRIBUTING以获取详细信息。
安全
如果您发现任何安全相关的问题,请通过电子邮件freek@spatie.be联系,而不是使用问题跟踪器。
明信片软件
您可以自由使用此软件包,但如果它进入您的生产环境,我们非常感激您从家乡寄给我们明信片,并提及您正在使用我们哪个软件包。
我们的地址是:Spatie,Samberstraat 69D,2060 安特卫普,比利时。
我们将所有收到的明信片发布在我们的公司网站上。
鸣谢
聚合根功能深受Frank De Jonge的优秀EventSauce软件包的启发。感谢Dries Vints在开发软件包期间提供了大量宝贵的反馈。
脚注
1 引自 Event Sourcing made Simple
许可证
MIT许可证(MIT)。请参阅许可证文件以获取更多信息。