From 8d638a47dd7b527f39267e1187e3bbee5f9331f7 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Tue, 10 Nov 2026 21:34:25 +0100 Subject: [PATCH 1/2] fix: handle failed database inserts in DatabaseHandler::push() --- src/Handlers/DatabaseHandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Handlers/DatabaseHandler.php b/src/Handlers/DatabaseHandler.php index 2912f48..473a571 100644 --- a/src/Handlers/DatabaseHandler.php +++ b/src/Handlers/DatabaseHandler.php @@ -94,7 +94,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ return QueuePushResult::failure($e->getMessage()); } - if ($jobId === 0) { + if ($jobId === false || $jobId === 0 || ! is_numeric($jobId)) { $err = new RuntimeException('Failed to insert job into the database.'); QueueEventManager::jobPushFailed( handler: $this->name(), @@ -107,7 +107,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ } // Set the job ID for the successful push event - $queueJob->id = $jobId; + $queueJob->id = (int) $jobId; // Emit job pushed event QueueEventManager::jobPushed( @@ -116,7 +116,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ job: $queueJob, ); - return QueuePushResult::success($jobId); + return QueuePushResult::success((int) $jobId); } /** From 1d745ef497007bc42d6cdb0998ec3e3bf4d6afb5 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Tue, 10 Nov 2026 21:46:22 +0100 Subject: [PATCH 2/2] test: add tests for DatabaseHandler::push() when model returns false or 0 --- tests/DatabaseHandlerTest.php | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/DatabaseHandlerTest.php b/tests/DatabaseHandlerTest.php index a23431c..4878586 100644 --- a/tests/DatabaseHandlerTest.php +++ b/tests/DatabaseHandlerTest.php @@ -13,14 +13,18 @@ namespace Tests; +use CodeIgniter\Events\Events; use CodeIgniter\I18n\Time; use CodeIgniter\Queue\Entities\QueueJob; use CodeIgniter\Queue\Enums\Status; +use CodeIgniter\Queue\Events\QueueEventManager; use CodeIgniter\Queue\Exceptions\QueueException; use CodeIgniter\Queue\Handlers\DatabaseHandler; use CodeIgniter\Queue\Models\QueueJobFailedModel; +use CodeIgniter\Queue\Models\QueueJobModel; use CodeIgniter\Test\ReflectionHelper; use Exception; +use ReflectionClass; use ReflectionException; use Tests\Support\Config\Queue as QueueConfig; use Tests\Support\Database\Seeds\TestDatabaseQueueSeeder; @@ -43,6 +47,13 @@ protected function setUp(): void $this->config = config(QueueConfig::class); } + protected function tearDown(): void + { + parent::tearDown(); + + Events::removeAllListeners(); + } + public function testDatabaseHandler(): void { $handler = new DatabaseHandler($this->config); @@ -93,6 +104,60 @@ public function testPush(): void ]); } + public function testPushWhenModelReturnsFalse(): void + { + $pushedTriggered = false; + $pushFailedTriggered = false; + + Events::on(QueueEventManager::JOB_PUSHED, static function () use (&$pushedTriggered): void { + $pushedTriggered = true; + }); + Events::on(QueueEventManager::JOB_PUSH_FAILED, static function () use (&$pushFailedTriggered): void { + $pushFailedTriggered = true; + }); + + $mockModel = $this->createMock(QueueJobModel::class); + $mockModel->expects($this->once()) + ->method('insert') + ->willReturn(false); + + $handler = $this->createHandlerWithMockModel($mockModel); + $result = $handler->push('queue', 'success', ['key' => 'value']); + + $this->assertFalse($result->getStatus()); + $this->assertNull($result->getJobId()); + $this->assertSame('Failed to insert job into the database.', $result->getError()); + $this->assertFalse($pushedTriggered); + $this->assertTrue($pushFailedTriggered); + } + + public function testPushWhenModelReturnsZero(): void + { + $pushedTriggered = false; + $pushFailedTriggered = false; + + Events::on(QueueEventManager::JOB_PUSHED, static function () use (&$pushedTriggered): void { + $pushedTriggered = true; + }); + Events::on(QueueEventManager::JOB_PUSH_FAILED, static function () use (&$pushFailedTriggered): void { + $pushFailedTriggered = true; + }); + + $mockModel = $this->createMock(QueueJobModel::class); + $mockModel->expects($this->once()) + ->method('insert') + ->willReturn(0); + + $handler = $this->createHandlerWithMockModel($mockModel); + $result = $handler->push('queue', 'success', ['key' => 'value']); + + $this->assertFalse($result->getStatus()); + $this->assertNull($result->getJobId()); + $this->assertSame('Failed to insert job into the database.', $result->getError()); + $this->assertFalse($pushedTriggered); + $this->assertTrue($pushFailedTriggered); + } + /** * @throws ReflectionException */ @@ -513,4 +578,14 @@ public function testListFailed(): void $list = $handler->listFailed('queue1'); $this->assertCount(1, $list); } + + private function createHandlerWithMockModel(QueueJobModel $mockModel): DatabaseHandler + { + $ref = new ReflectionClass(DatabaseHandler::class); + $handler = $ref->newInstanceWithoutConstructor(); + $this->setPrivateProperty($handler, 'config', $this->config); + $this->setPrivateProperty($handler, 'jobModel', $mockModel); + + return $handler; + } }