blackfrog / laravel-event-sourcing-dynamodb
Spatie Laravel Event Sourcing 的 AWS DynamoDB 驱动程序
Requires
- php-64bit: ^8.2
- aws/aws-sdk-php: ^3.261.16
- illuminate/contracts: ^10.0
- spatie/laravel-event-sourcing: ^7.3.3
- spatie/laravel-package-tools: ^1.14.2
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.9
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^8.0
- pestphp/pest: ^2.0
- pestphp/pest-plugin-arch: ^2.0
- pestphp/pest-plugin-laravel: ^2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- symfony/var-dumper: ^6.2
This package is auto-updated.
Last update: 2024-09-09 04:04:59 UTC
README
! 进行中 ! 目前还不适合使用。请等待第一个 SemVer 版本发布。
为 spatie/laravel-event-sourcing 提供一个 DynamoDB 驱动程序,允许以无服务器方式存储事件和快照数据。
首次发布 TODO 列表
- 审查处理事件元数据的方法,确保其兼容性。
- 复制并修改主包测试套件中的任何部分,以提供更多端到端覆盖。
特性
- 为
StoredEventRepository和SnapshotRepository提供 DynamoDB 实现。 - 与 Spatie Eloquent 实现的兼容性。见 细微差异。
- 无限制的 快照 大小。
- 创建表的命令,让您快速入门。
- 可选支持 强一致性读取(但有限制)。
- 延迟集合 支持,由 AWS 的 PHP 分页器支持。
细微差异
- 默认的
EloquentStoredEventRepository:store()实现将null$uuid参数转换为空字符串以进行存储。DynamoDB 不允许空字符串,因此我们将其存储为字符串'null'。 - 目前不支持 AggregateRoots 上的
persistInTransaction(),该包本身不使用此方法,但您可能需要。见 更多信息。
要求
- 64位 PHP 8.2
"spatie/laravel-event-sourcing": "^7.3.3",
我应该使用 DynamoDB 吗?
DynamoDB 带来许多优势
- 它是无服务器架构,从零开始扩展成本和容量完全基于使用情况,与通过 Eloquent 支持的数据库解决方案不同。
- 当您遵循计划的访问模式时,它既快又便宜,即使用 Spatie 接口的方法,并定期使用快照来避免每次都检索所有事件。
- 它可以轻松地将您连接到更广泛的 AWS 事件源生态系统,通过 DynamoDB Streams 和 事件桥 将事件与其他应用程序和服务共享。
- 它与 Laravel Vapor 配合得天衣无缝,消除了任何固定的每月 RDS 成本。
- Laravel 已经内置了对 DynamoDB 的官方支持,作为缓存和会话驱动程序,因此您也可以使用这些驱动程序来构建更简单、更一致的纯无服务器堆栈。
当它不适合您时
- 您想避免锁定在 AWS 作为云供应商。
- 您希望添加许多自定义查询,用于事件或快照,而当前软件包尚未提供。
- 您希望在将来能够对您的DynamoDB事件表进行复杂的分析和查询。这可能变得昂贵且缓慢。《Fathom Analytics》在处理这个问题时遇到了困难。[了解更多](https://usefathom.com/blog/ditched-dynamodb)。
- 您不希望花时间了解DynamoDB及其优势和劣势。
- 您还没有阅读完这份README!
工作原理
事件
- 事件存储在一张表中,其中
aggregate_uuid作为HASH(分区)键,id作为RANGE键。 - 事件表有两个索引,以覆盖
StoredEventRepository接口的行为。 - 一个全局二级索引(包含所有属性),其中
id既是HASH键也是RANGE键,支持在不包含聚合uuid的情况下获取事件,同时保留其顺序,find($id)和retrieveAll(null)都使用这个索引。 - 一个本地二级索引(仅包含键)将
version_id(版本和id的合成)作为RANGE,以支持getLatestAggregateVersion()。如果您确实不需要读一致性功能,可以将其更改为GSI。有关更多信息,请参阅DynamoDB限制。 - 使用基于当前微秒时间戳生成的递增整数id来保留事件顺序。这对于与Spatie包的兼容性是必要的,有关详细信息,请参阅事件ID。
快照
- 快照存储在单个表中,但作为一项或多项条目,允许快照的大小超过DynamoDB的400KB限制。该表将
aggregate_uuid作为HASH键,将id_part作为RANGE键。 id_part是随机生成的int id和快照的'部分号'的合成。这有两个作用:它意味着在查询时(使用DESC排序)会首先返回最新的快照,如果快照需要存储多个DynamoDB条目,则可以按正确的顺序返回快照部分。- 在您聚合根的
getState()方法输出上使用PHPserialize(),然后将结果base64编码,并在无法适应单个DynamoDB条目(400KB限制)时将其拆分为多个部分。 - 在后台将快照检索的各部分重新组合,以恢复您的聚合根。
- 快照的总大小不受DynamoDB的限制,仅受处理它们的进程的PHP内存限制约束。
读取一致性
- 您可以使用
read_consistency配置键(默认为false)配置从DynamoDB进行一致性读取。[了解更多](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html)。这仅适用于您将聚合根UUID作为参数传递的方法。一些EventRepository上的方法调用(如find($id)和retrieveAll(null))将保持最终一致性。
延迟集合
- 该软件包实现了一个分页器,允许您以LazyCollections的形式遍历大型结果集,由AWS PHP分页器支持。但是,请注意,这可能导致重复的DynamoDB请求。如果您想避免这种情况,并在访问后保留结果在内存中,只需在集合上调用
->remember()即可。
限制
DynamoDB
- 单个事件的大小不能超过400KB,这是DynamoDB条目的最大大小。
- 由于使用了本地二级索引,所有事件数据的最大总大小限制为10GB。如果您不打算使用读取一致性功能,可以在创建表之前将索引
aggregate_uuid-version-id-index移动到GlobalSecondaryIndexes中,以消除此限制。 - 该包期望
PAY_PER_REQUEST计费模式的行为,并且目前不支持按需吞吐量。例如,没有处理超出吞吐量的异常,也没有为此提供等待/重试机制。
事务
- spatie包在其
AggregateRoot基类上有一个名为persistInTransaction()的方法,这个方法在事件存储周围创建一个Laravel数据库事务。目前没有让存储库知道这个事务的方法,所以我们无法为DynamoDB实现它。这个方法在包内部并不使用,所以您只需要了解如果您自己使用这个方法。
事件 ID
- 此包为事件生成自己的64位
intId。Spatie包的接口期望整数id,逻辑期望它们是递增的。DynamoDB不提供递增的id。 - Ids由当前微秒时间戳表示的整数加上末尾附加的3个随机数字组成。这近似了期望的事件顺序的递增行为,而随机数字增加了在两个ID在同一个微秒生成时的碰撞抵抗。
- 碰撞是可能的,但不太可能,目前在代码中未处理,后果将取决于您应用程序的设计。
- 请考虑,在规模较大时,服务器之间的时钟偏差可能会引起问题。
- 您可以通过实现
IdGenerator接口并更新配置密钥id_generator来切换到您自己的ID生成实现。
'id_generator' => TimeStampIdGenerator::class,
- 您可以通过实现
TimestampProvider接口并更新配置密钥id_timestamp_provider来切换到您自己的提供的TimeStampIdGenerator实现。如果您返回较短的timestamp(例如秒或毫秒),TimeStampIdGenerator将使用随机数字填充64位Int的其余部分。
'id_timestamp_provider' => TimeStampIdGenerator::class,
入门
安装
使用composer安装该包
composer require blackfrog/laravel-event-sourcing-dynamodb
配置
使用以下命令发布配置文件:
php artisan vendor:publish --tag="laravel-event-sourcing-dynamodb-config"
请检查配置密钥dynamodb-client并确保设置了适当的ENV变量,或者如果您发现包默认值与您冲突,您可能希望使用自己的ENV变量名称。该数组是传递给Aws\DynamoDb\DynamoDbClient的配置数组,因此您可以修改它以使用AWS包支持的任何内容,包括替代身份验证选项。如果您已经使用AWS,例如使用DynamoDB作为Laravel的缓存驱动程序,您应该检查并调整此包的配置,以避免混淆或重复。
您可以使用event-table和snapshot-table配置密钥更改默认表名。
创建 DynamoDB 表
您可以使用php artisan event-sourcing-dynamodb:create-tables创建相关的DynamoDb表。这样做需要适当的AWS权限,在生产场景中使用可能不明智。您可以在event-sourcing-dynamodb.php中查看(并自行承担风险修改)表规范。对于生产环境,我们建议您将这些表规范移动到您首选的AWS资源管理机制中,例如Terraform或CloudFormation。
更新 Spatie Laravel Event Sourcing 配置
在config/event-sourcing.php中更新Spatie Laravel Event Sourcing包的配置,将stored_event_repository的值设置为DynamoDbStoredEventRepository::class,将snapshot_repository的值设置为DynamoDbSnapshotRepository::class。
测试
运行测试套件需要DynamoDBLocal,有关设置信息请参阅本地开发。
测试套件期望此服务存在并在默认端口上运行。
运行
composer test
本地开发
对于本地开发,您可以使用:DynamoDB Local。与实际服务相比,存在一些行为上的细微差异,我们建议在您的AWS账户中针对真实的DynamoDB进行测试,然后再启动您的项目。
未来路线图想法
- 支持自动删除具有DynamoDB生存时间(TTL)功能的事件的自动事件删除,该功能按事件指定。
- 对读取一致性模式有更细粒度的控制,例如,可以按方法配置,或者能够动态更改仓库绑定以获取一个读取一致性的绑定。
- 支持按配置容量计费,特别是处理异常和重试。
变更日志
有关最近更改的更多信息,请参阅变更日志。
鸣谢
许可证
MIT 许可证(MIT)。有关更多信息,请参阅许可文件。