Laravel:如果其他侦听器捕获异常,如何回滚侦听器



有一个事件有四个侦听器。侦听器正在执行一些财务任务,因此,如果其中一个任务失败,则所有以前的侦听器都必须回滚以验证整个系统的一致性。我该怎么做?

当任务在功能中时,我可以这样做:

f1();
function f1(){
try{
DB:BeginTransaction();
//do the tasks
DB::commit();
f2();
}catch(Throwable $t){
DB::rollback();
}
}
function f2(){
try{
DB:BeginTransaction();
//do the tasks
DB::commit();
f3();
}catch(Throwable $t){
DB::rollback();
throw $t;
}    
}
function f3(){
try{
DB:BeginTransaction();
//do the tasks
DB::commit();
}catch(Throwable $t){
DB::rollback();
throw $t;
}    
}

正如您所看到的,当一个函数(比如f3()(遇到异常时,它会回滚并抛出新的异常。因此,函数f2()中的调用行遇到异常,它也会回滚并再次抛出异常,它会导致函数f1()中的调用线再次遇到异常并回滚。因此,catch中的throw链验证了以前函数中的所有数据库插入都是回滚的。

但如果是听众,我不知道如何处理。

您为每个函数执行单独的事务,因此它们是独立的。f3()无法回滚f1(),因为您正在调用f2f3之前提交它。

然而,你可以这样做:

DB::beginTransaction();
try {
f1();
f2();
f3();
DB::commit();
} catch (/* your exceptions here */) { // QueryException is a good one to catch
DB::rollBack();
} catch (Exception $e) { // add generic Exception for good measure
DB::rollBack();
}

其中f1f2f3只是任务。

function f1() {
// f1 tasks
}
function f2() {
// f2 tasks
}
function f3() {
// f3 tasks
}

或者在一切完成后直接拨打commit

f2();
DB::commit();
...
f3();
DB::commit();

至于事件侦听器。。。我不确定,但也许在传递连接实例($connection = DB::getConnection();nad然后使用它进行查询.$connection->query()->.....(时将它们链接起来可以工作。

文档中有一些关于在事务中使用(排队的(侦听器的信息,这里是

https://laravel.com/docs/queues#jobs-和数据库事务

最新更新