diff --git a/src/RequestInsurance/RequestInsuranceWorker.php b/src/RequestInsurance/RequestInsuranceWorker.php index 77a461e..863d350 100644 --- a/src/RequestInsurance/RequestInsuranceWorker.php +++ b/src/RequestInsurance/RequestInsuranceWorker.php @@ -139,29 +139,29 @@ public function run(bool $runOnlyOnce = false): void */ protected function handleCycleFailure(Throwable $throwable): void { - if ( ! $this->wasCausedByLostConnection($throwable)) { + if ($this->wasCausedByLostConnection($throwable)) { + $this->consecutiveLostConnections++; + + $message = sprintf( + 'RequestInsurance Worker (#%s) lost its database connection during %s and is reconnecting (%d in a row)', + $this->runningHash, + $this->currentPhase, + $this->consecutiveLostConnections + ); + + if ($this->consecutiveLostConnections > self::QUIET_LOST_CONNECTION_RECOVERIES) { + Log::error($message, ['exception' => $throwable]); + } else { + Log::debug($message); + } + } else { $this->consecutiveLostConnections = 0; Log::error($throwable); - - return; - } - - $this->consecutiveLostConnections++; - - $message = sprintf( - 'RequestInsurance Worker (#%s) lost its database connection during %s and is reconnecting (%d in a row)', - $this->runningHash, - $this->currentPhase, - $this->consecutiveLostConnections - ); - - if ($this->consecutiveLostConnections > self::QUIET_LOST_CONNECTION_RECOVERIES) { - Log::error($message, ['exception' => $throwable]); - } else { - Log::debug($message); } + // The connection is given up on no matter what failed the cycle, since a failure can leave it in a + // state it never recovers from on its own, such as a transaction its driver still considers open. rescue(fn () => $this->reconnectToDatabase(), null, false); } diff --git a/tests/Unit/RequestInsuranceWorkerTest.php b/tests/Unit/RequestInsuranceWorkerTest.php index 65e6090..df97829 100644 --- a/tests/Unit/RequestInsuranceWorkerTest.php +++ b/tests/Unit/RequestInsuranceWorkerTest.php @@ -4,6 +4,7 @@ use Exception; use Throwable; +use PDOException; use Tests\TestCase; use GuzzleHttp\Psr7\Request; use Illuminate\Support\Facades\Log; @@ -501,7 +502,20 @@ public function test_it_reports_cycle_failures_that_are_not_lost_connections(): $worker->exposeReportCycleFailure($throwable); - $this->assertSame(0, $worker->reconnects); + $this->assertSame(1, $worker->reconnects); + } + + public function test_it_gives_up_on_a_connection_holding_a_stranded_transaction(): void + { + $worker = $this->getWorkerProbe(); + + Log::shouldReceive('error')->times(5); + + foreach (range(1, 5) as $ignored) { + $worker->exposeReportCycleFailure(new PDOException('There is already an active transaction')); + } + + $this->assertSame(5, $worker->reconnects); } /**