bentools/doctrine-safe-events

在事务完成后触发 postPersist / postUpdate / postRemove 事件。

1.0.1 2023-01-05 13:05 UTC

This package is auto-updated.

Last update: 2024-09-05 16:59:21 UTC


README

CI Workflow Coverage

Doctrine 安全 post* 事件

当对数据库服务器执行相应的 SQL 查询(INSERT / UPDATE / DELETE)时,Doctrine 的 postPersist, postUpdate 和 postRemove 事件被触发。

幕后发生的事情是,Doctrine 创建一个包装事务,运行 SQL 查询,然后提交事务。

然而,这些事件是立即触发的,例如,不是在事务完成之后,这意味着

  • 如果包装事务失败,事件仍然已经触发(这意味着你信任生成的主键值,尽管它们将被回滚)
  • 如果包装事务花费了一些时间(通常在行锁定期间),你将获得插入的/更新的/删除的信息,但实际上它还没有完成(这意味着如果你在事件触发后运行一些异步过程,你最终处理的是不更新的数据)

背景

这个仓库的想法确实来自于以下问题

  • 一个实体被持久化,然后调用 $em->flush()
  • postPersist 事件监听器获取实体的 id,然后要求一个工作员通过 Symfony Messenger 进行一些异步处理
  • 工作员查询数据库以获取实体的 id,并得到一个 EntityNotFound 异常(尚未发生 COMMIT
  • 主线程上的 flush 操作完成,并触发 postFlush 事件(但它不包含插入的/更新的/删除的实体)

我们的解决方案

如果你遇到相同类型的问题,你可以用

  • Bentools\DoctrineSafeEvents\SafeEvents::POST_PERSIST(并将 safePostPersist 实现为 postPersist 的替代)
  • Bentools\DoctrineSafeEvents\SafeEvents::POST_UPDATE(并将 safePostUpdate 实现为 postUpdate 的替代)
  • Bentools\DoctrineSafeEvents\SafeEvents::POST_REMOVE(并将 safePostRemove 实现为 postRemove 的替代)

基本上,这个库将收集计划插入/更新/删除的实体,但它将延迟事件触发,直到发生 postFlush

安装

composer require bentools/doctrine-safe-events

在 Symfony 中的使用

尽管这个库没有依赖 Symfony,但你可以在你的 Symfony 项目中轻松使用它

Bentools\DoctrineSafeEvents\SafeEventsDispatcher:
    tags:
        - { name: 'doctrine.event_subscriber' }
        - { name: 'kernel.reset', method: 'reset' }

示例使用

declare(strict_types=1);

namespace App;

use Bentools\DoctrineSafeEvents\SafeEvents;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\Persistence\Event\LifecycleEventArgs;

#[AsDoctrineListener(SafeEvents::POST_PERSIST)]
final class SomeListener
{
    public function safePostPersist(LifecycleEventArgs $eventArgs): void
    {
        // ...
    }
}

测试

composer test

许可

MIT.