mehr-it/lara-transaction-waiting-events

等待数据库事务完成的等待事件(仅MySQL)

1.4.0 2023-04-18 18:22 UTC

README

此包实现了Laravel的队列事件,这些事件保证在关闭任何挂起的数据库事务之前不会被处理。

为什么这是必要的?

队列事件监听器通常依赖于事件发射器写入的数据。即使数据库事务的使用是必需的,或者至少是强烈推荐的,Laravel也不提供在所有挂起数据库事务完成后阻止事件处理机制。

许多处理事件和事务的其他包,只是在数据库事务提交之前将事件收集在内存中。然而,如果在提交之后和将所有事件发送到队列之前出现错误条件,你将丢失一些事件。想象一下,由于丢失事件而未处理的客户订单...

最好先发射事件,然后在事件发送后提交数据库事务(注意:事件处理器必须优雅地处理事务回滚的情况,这通常很简单)。

它是如何工作的?

只要在数据库事务打开时向队列监听器派遣事件,事件调度器就会将一个锁条目写入数据库,该条目在事务关闭时释放。队列监听器在调用之前等待“事务锁”释放。这就是我们所需要的一切。

重要:即使事务已回滚,事件监听器也会被调用!这取决于监听器来处理这种情况。由于始终是一个好主意,监听器在调用时检查任何先决条件(而不是假设系统的特定状态),因此这里不应有额外的工作。

实现细节

此包扩展了Laravel的事件调度器,在调用带有《WaitsForTransactions》接口的队列监听器时设置“事务锁”。它使用MySQL锁定函数来设置“事务锁”。因此,此包仅适用于MySQL连接。锁实现确保在事务结束时始终删除锁。无论提交、回滚还是进程意外终止。

在调用队列监听器之前,会检查是否存在任何事务锁。如果事务锁仍然存在,则将事件处理作业释放到队列中,稍后重试。

要求

  • Laravel >= 5.8
  • PHP >= 7.1
  • MySQL >= 5.7.5

此包仅适用于MySQL数据库连接!

安装

composer require mehr-it/lara-transaction-waiting-events

此包使用Laravel的包自动发现,因此服务提供者和别名将自动加载。

使用

要做的只有一件事,让队列事件处理器等待事务完成。必须将《WaitsForTransactions》标记接口添加到监听器类中

class Listener implements ShouldQueue, WaitsForTransactions
{
    public function handle($event) {

    }
}

指定事务锁详细信息

监听器可以指定一些事务锁选项

自定义连接

默认情况下,监听器仅等待默认DB连接的事务。你可以传递另一个连接名称或使用《waitForTransactions》属性指定多个连接

class Listener implements ShouldQueue, WaitsForTransactions
{
    public $waitForTransactions = ['default-connection', 'secondary-connection'];
 
    public function handle($event) {
    
    }
}

超时和重试延迟

默认情况下,监听器最多等待1秒以完成事务。如果事务尚未完成,处理程序任务将被释放回队列,并在5秒后重试。如果您正在使用长时间运行的事务,您可能需要调整这些值

class Listener implements ShouldQueue, WaitsForTransactions
{
    // the time to wait for transactions to complete
    public $waitForTransactionsTimeout = 7;
    
    // the retry delay
    public $waitForTransactionsRetryAfter = 30;
  
 
    public function handle($event) {
    
    }
}

禁用事务等待事件

有时——尤其是在运行测试或使用“同步”队列驱动程序时——您可能希望禁用事务等待事件,即使事务尚未提交,也将其分派。您可以通过在.env文件中将EVENTS_WAIT_FOR_TRANSACTIONS设置为false来实现这一点

EVENTS_WAIT_FOR_TRANSACTIONS=false