inTransaction())throw new LogicException('Retryable work must own its transaction.'); for($attempt=1;$attempt<=3;$attempt++){ $db->beginTransaction(); try{ $result=$work($db);$db->commit();return $result; }catch(Throwable $error){ if($db->inTransaction())$db->rollBack(); $retryable=$error instanceof PDOException && (in_array((int)($error->errorInfo[1]??0),[1205,1213],true)||$error->getCode()==='40001'); if(!$retryable||$attempt===3)throw $error; usleep(random_int(10000,30000)*$attempt); } } throw new LogicException('Transaction attempts exhausted.'); } }