mehr-it / lara-transaction-waiting-events
等待数据库事务完成的等待事件(仅MySQL)
Requires
- php: >=7.1
- laravel/framework: ^5.8|^6.0|^7.0|^8.0
Requires (Dev)
- orchestra/testbench: ^3.8|^4.0|^5.0|^6.0
- phpunit/phpunit: ^7.4|^8.0
This package is auto-updated.
Last update: 2024-09-18 21:25:11 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