blackfrog/laravel-event-sourcing-dynamodb

Spatie Laravel Event Sourcing 的 AWS DynamoDB 驱动程序

dev-main 2023-07-03 01:19 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Test Coverage Total Downloads

! 进行中 ! 目前还不适合使用。请等待第一个 SemVer 版本发布。

spatie/laravel-event-sourcing 提供一个 DynamoDB 驱动程序,允许以无服务器方式存储事件和快照数据。

首次发布 TODO 列表

  • 审查处理事件元数据的方法,确保其兼容性。
  • 复制并修改主包测试套件中的任何部分,以提供更多端到端覆盖。

特性

  • StoredEventRepositorySnapshotRepository 提供 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()方法输出上使用PHP serialize(),然后将结果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位int Id。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-tablesnapshot-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)。有关更多信息,请参阅许可文件