From 4f8ca107201500f673b798b0820681803fd04009 Mon Sep 17 00:00:00 2001 From: michalsn Date: Fri, 30 May 2025 07:56:59 +0200 Subject: [PATCH 1/4] feat: return jobID after push instead of the bool value --- src/Handlers/BaseHandler.php | 4 ++-- src/Handlers/DatabaseHandler.php | 6 ++++-- src/Handlers/PredisHandler.php | 8 +++++--- src/Handlers/RedisHandler.php | 8 +++++--- src/Payloads/ChainBuilder.php | 4 ++-- tests/DatabaseHandlerTest.php | 14 +++++++------- tests/Payloads/ChainBuilderTest.php | 8 ++++---- tests/PredisHandlerTest.php | 10 +++++----- tests/PushAndPopWithDelayTest.php | 4 ++-- tests/RedisHandlerTest.php | 10 +++++----- 10 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index 03a6a57..7ee4ef9 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -39,7 +39,7 @@ abstract class BaseHandler abstract public function name(): string; - abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool; + abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string; abstract public function pop(string $queue, array $priorities): ?QueueJob; @@ -153,7 +153,7 @@ public function setPriority(string $priority): static * * @param Closure $callback Chain definition callback */ - public function chain(Closure $callback): bool + public function chain(Closure $callback): ?string { $chainBuilder = new ChainBuilder($this); $callback($chainBuilder); diff --git a/src/Handlers/DatabaseHandler.php b/src/Handlers/DatabaseHandler.php index 88869b6..26419e1 100644 --- a/src/Handlers/DatabaseHandler.php +++ b/src/Handlers/DatabaseHandler.php @@ -47,7 +47,7 @@ public function name(): string * * @throws ReflectionException */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string { $this->validateJobAndPriority($queue, $job); @@ -62,7 +62,9 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $this->priority = $this->delay = null; - return $this->jobModel->insert($queueJob, false); + $jobId = $this->jobModel->insert($queueJob); + + return $jobId !== 0 ? (string) $jobId : null; } /** diff --git a/src/Handlers/PredisHandler.php b/src/Handlers/PredisHandler.php index 4b64990..ace392f 100644 --- a/src/Handlers/PredisHandler.php +++ b/src/Handlers/PredisHandler.php @@ -59,7 +59,7 @@ public function name(): string /** * Add job to the queue. */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string { $this->validateJobAndPriority($queue, $job); @@ -67,8 +67,10 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $availableAt = Time::now()->addSeconds($this->delay ?? 0); + $jobId = random_string('numeric', 16); + $queueJob = new QueueJob([ - 'id' => random_string('numeric', 16), + 'id' => $jobId, 'queue' => $queue, 'payload' => new Payload($job, $data, $metadata), 'priority' => $this->priority, @@ -81,7 +83,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $this->priority = $this->delay = null; - return $result > 0; + return $result > 0 ? $jobId : null; } /** diff --git a/src/Handlers/RedisHandler.php b/src/Handlers/RedisHandler.php index dc86d5b..790d485 100644 --- a/src/Handlers/RedisHandler.php +++ b/src/Handlers/RedisHandler.php @@ -76,7 +76,7 @@ public function name(): string * * @throws RedisException */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string { $this->validateJobAndPriority($queue, $job); @@ -84,8 +84,10 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $availableAt = Time::now()->addSeconds($this->delay ?? 0); + $jobId = random_string('numeric', 16); + $queueJob = new QueueJob([ - 'id' => random_string('numeric', 16), + 'id' => $jobId, 'queue' => $queue, 'payload' => new Payload($job, $data, $metadata), 'priority' => $this->priority, @@ -98,7 +100,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $this->priority = $this->delay = null; - return $result > 0; + return $result > 0 ? $jobId : null; } /** diff --git a/src/Payloads/ChainBuilder.php b/src/Payloads/ChainBuilder.php index 73479d2..34de95e 100644 --- a/src/Payloads/ChainBuilder.php +++ b/src/Payloads/ChainBuilder.php @@ -44,10 +44,10 @@ public function push(string $queue, string $jobName, array $data = []): ChainEle /** * Dispatch the chain of jobs */ - public function dispatch(): bool + public function dispatch(): ?string { if ($this->payloads->count() === 0) { - return true; + return null; } $current = $this->payloads->shift(); diff --git a/tests/DatabaseHandlerTest.php b/tests/DatabaseHandlerTest.php index 507f917..1ddc7c6 100644 --- a/tests/DatabaseHandlerTest.php +++ b/tests/DatabaseHandlerTest.php @@ -85,7 +85,7 @@ public function testPush(): void $handler = new DatabaseHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]), @@ -103,7 +103,7 @@ public function testPushWithPriority(): void $handler = new DatabaseHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]), @@ -122,7 +122,7 @@ public function testPushAndPopWithPriority(): void $handler = new DatabaseHandler($this->config); $result = $handler->push('queue', 'success', ['key1' => 'value1']); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key1' => 'value1'], 'metadata' => []]), @@ -132,7 +132,7 @@ public function testPushAndPopWithPriority(): void $result = $handler->setPriority('high')->push('queue', 'success', ['key2' => 'value2']); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key2' => 'value2'], 'metadata' => []]), @@ -161,7 +161,7 @@ public function testPushWithDelay(): void $handler = new DatabaseHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $availableAt = 1703859376; @@ -188,7 +188,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ @@ -221,7 +221,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ diff --git a/tests/Payloads/ChainBuilderTest.php b/tests/Payloads/ChainBuilderTest.php index 304f5ae..8ab52ea 100644 --- a/tests/Payloads/ChainBuilderTest.php +++ b/tests/Payloads/ChainBuilderTest.php @@ -63,7 +63,7 @@ public function testChainWithSingleJob(): void $chain->push('queue', 'success', ['key' => 'value']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ @@ -84,7 +84,7 @@ public function testEmptyChain(): void // No jobs added }); - $this->assertTrue($result); + $this->assertNull($result); $this->seeInDatabase('queue_jobs', []); } @@ -99,7 +99,7 @@ public function testMultipleDifferentQueues(): void ->push('queue2', 'success', ['key2' => 'value2']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue1', 'payload' => json_encode([ @@ -132,7 +132,7 @@ public function testChainWithManyJobs(): void ->push('queue', 'success', ['key3' => 'value3']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ diff --git a/tests/PredisHandlerTest.php b/tests/PredisHandlerTest.php index 226732b..17b8e90 100644 --- a/tests/PredisHandlerTest.php +++ b/tests/PredisHandlerTest.php @@ -72,7 +72,7 @@ public function testPush(): void $handler = new PredisHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:low')); @@ -92,7 +92,7 @@ public function testPushWithPriority(): void $handler = new PredisHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:high')); @@ -114,7 +114,7 @@ public function testPushWithDelay(): void $handler = new PredisHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue-delay:default')); @@ -140,7 +140,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:low')); @@ -180,7 +180,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertTrue($result); + $this->assertNotNull($result); $predis = self::getPrivateProperty($handler, 'predis'); // Should be in high priority queue diff --git a/tests/PushAndPopWithDelayTest.php b/tests/PushAndPopWithDelayTest.php index db49b81..70a85a3 100644 --- a/tests/PushAndPopWithDelayTest.php +++ b/tests/PushAndPopWithDelayTest.php @@ -64,11 +64,11 @@ public function testPushAndPopWithDelay(string $name, string $class): void $handler = new $class($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key1' => 'value1']); - $this->assertTrue($result); + $this->assertNotNull($result); $result = $handler->push('queue-delay', 'success', ['key2' => 'value2']); - $this->assertTrue($result); + $this->assertNotNull($result); if ($name === 'database') { $this->seeInDatabase('queue_jobs', [ diff --git a/tests/RedisHandlerTest.php b/tests/RedisHandlerTest.php index aa71240..82a2066 100644 --- a/tests/RedisHandlerTest.php +++ b/tests/RedisHandlerTest.php @@ -69,7 +69,7 @@ public function testPush(): void $handler = new RedisHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:low')); @@ -86,7 +86,7 @@ public function testPushWithPriority(): void $handler = new RedisHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:high')); @@ -108,7 +108,7 @@ public function testPushWithDelay(): void $handler = new RedisHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertTrue($result); + $this->assertNotNull($result); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue-delay:default')); @@ -134,7 +134,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertTrue($result); + $this->assertNotNull($result); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:low')); @@ -174,7 +174,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertTrue($result); + $this->assertNotNull($result); $redis = self::getPrivateProperty($handler, 'redis'); // Should be in high priority queue From 8c41b171e77cdc684a27b32cdf45e14d49f78da8 Mon Sep 17 00:00:00 2001 From: michalsn Date: Fri, 30 May 2025 08:22:27 +0200 Subject: [PATCH 2/4] fix phpcpd --- src/Handlers/PredisHandler.php | 3 +-- src/Handlers/RedisHandler.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Handlers/PredisHandler.php b/src/Handlers/PredisHandler.php index ace392f..b0ebd1d 100644 --- a/src/Handlers/PredisHandler.php +++ b/src/Handlers/PredisHandler.php @@ -65,10 +65,9 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ helper('text'); + $jobId = random_string('numeric', 16); $availableAt = Time::now()->addSeconds($this->delay ?? 0); - $jobId = random_string('numeric', 16); - $queueJob = new QueueJob([ 'id' => $jobId, 'queue' => $queue, diff --git a/src/Handlers/RedisHandler.php b/src/Handlers/RedisHandler.php index 790d485..66d2050 100644 --- a/src/Handlers/RedisHandler.php +++ b/src/Handlers/RedisHandler.php @@ -83,8 +83,7 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ helper('text'); $availableAt = Time::now()->addSeconds($this->delay ?? 0); - - $jobId = random_string('numeric', 16); + $jobId = random_string('numeric', 16); $queueJob = new QueueJob([ 'id' => $jobId, From 2d754b836284f21678c4a08b2ce8a9148e565966 Mon Sep 17 00:00:00 2001 From: michalsn Date: Thu, 5 Jun 2025 22:15:27 +0200 Subject: [PATCH 3/4] feat: return QueuePushResult from push() instead of bool --- docs/basic-usage.md | 10 ++++- src/Handlers/BaseHandler.php | 5 ++- src/Handlers/DatabaseHandler.php | 17 +++++--- src/Handlers/PredisHandler.php | 17 ++++++-- src/Handlers/RedisHandler.php | 21 ++++++--- src/Payloads/ChainBuilder.php | 5 ++- src/QueuePushResult.php | 49 +++++++++++++++++++++ tests/DatabaseHandlerTest.php | 14 +++--- tests/Payloads/ChainBuilderTest.php | 8 ++-- tests/PredisHandlerTest.php | 10 ++--- tests/QueuePushResultTest.php | 68 +++++++++++++++++++++++++++++ tests/RedisHandlerTest.php | 10 ++--- 12 files changed, 194 insertions(+), 40 deletions(-) create mode 100644 src/QueuePushResult.php create mode 100644 tests/QueuePushResultTest.php diff --git a/docs/basic-usage.md b/docs/basic-usage.md index 3204e39..b91ae37 100644 --- a/docs/basic-usage.md +++ b/docs/basic-usage.md @@ -160,6 +160,12 @@ service('queue')->push('emails', 'email', ['message' => 'Email message goes here We will be pushing `email` job to the `emails` queue. +As a result of calling the `push()` method, you will receive a `QueuePushResult` object, which you can inspect if needed. It provides the following information: + +- `getStatus()`: Indicates whether the job was successfully added to the queue. +- `getJobId()`: Returns the ID of the job that was added to the queue. +- `getError()`: Returns any error that occurred if the job was not added. + ### Sending chained jobs to the queue Sending chained jobs is also simple and lets you specify the particular order of the job execution. @@ -172,9 +178,11 @@ service('queue')->chain(function($chain) { }); ``` -In the example above, we will send jobs to the `reports` and `emails` queue. First, we will generate a report for given user with the `generate-report` job, after this, we will send an email with `email` job. +In the example above, we will send jobs to the `reports` and `emails` queues. First, we will generate a report for given user with the `generate-report` job, after this, we will send an email with `email` job. The `email` job will be executed only if the `generate-report` job was successful. +As with the `push()` method, calling the `chain()` method also returns a `QueuePushResult` object. + ### Consuming the queue Since we sent our sample job to queue `emails`, then we need to run the worker with the appropriate queue: diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index 7ee4ef9..f364802 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -22,6 +22,7 @@ use CodeIgniter\Queue\Models\QueueJobFailedModel; use CodeIgniter\Queue\Payloads\ChainBuilder; use CodeIgniter\Queue\Payloads\PayloadMetadata; +use CodeIgniter\Queue\QueuePushResult; use CodeIgniter\Queue\Traits\HasQueueValidation; use ReflectionException; use Throwable; @@ -39,7 +40,7 @@ abstract class BaseHandler abstract public function name(): string; - abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string; + abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult; abstract public function pop(string $queue, array $priorities): ?QueueJob; @@ -153,7 +154,7 @@ public function setPriority(string $priority): static * * @param Closure $callback Chain definition callback */ - public function chain(Closure $callback): ?string + public function chain(Closure $callback): QueuePushResult { $chainBuilder = new ChainBuilder($this); $callback($chainBuilder); diff --git a/src/Handlers/DatabaseHandler.php b/src/Handlers/DatabaseHandler.php index 26419e1..403e7cd 100644 --- a/src/Handlers/DatabaseHandler.php +++ b/src/Handlers/DatabaseHandler.php @@ -21,6 +21,7 @@ use CodeIgniter\Queue\Models\QueueJobModel; use CodeIgniter\Queue\Payloads\Payload; use CodeIgniter\Queue\Payloads\PayloadMetadata; +use CodeIgniter\Queue\QueuePushResult; use ReflectionException; use Throwable; @@ -44,10 +45,8 @@ public function name(): string /** * Add job to the queue. - * - * @throws ReflectionException */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult { $this->validateJobAndPriority($queue, $job); @@ -62,9 +61,17 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ $this->priority = $this->delay = null; - $jobId = $this->jobModel->insert($queueJob); + try { + $jobId = $this->jobModel->insert($queueJob); + } catch (Throwable $e) { + return QueuePushResult::failure($e->getMessage()); + } + + if ($jobId === 0) { + return QueuePushResult::failure('Failed to insert job into the database.'); + } - return $jobId !== 0 ? (string) $jobId : null; + return QueuePushResult::success($jobId); } /** diff --git a/src/Handlers/PredisHandler.php b/src/Handlers/PredisHandler.php index b0ebd1d..22be7cf 100644 --- a/src/Handlers/PredisHandler.php +++ b/src/Handlers/PredisHandler.php @@ -22,6 +22,7 @@ use CodeIgniter\Queue\Interfaces\QueueInterface; use CodeIgniter\Queue\Payloads\Payload; use CodeIgniter\Queue\Payloads\PayloadMetadata; +use CodeIgniter\Queue\QueuePushResult; use Exception; use Predis\Client; use Throwable; @@ -59,13 +60,13 @@ public function name(): string /** * Add job to the queue. */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult { $this->validateJobAndPriority($queue, $job); helper('text'); - $jobId = random_string('numeric', 16); + $jobId = (int) random_string('numeric', 16); $availableAt = Time::now()->addSeconds($this->delay ?? 0); $queueJob = new QueueJob([ @@ -78,11 +79,19 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ 'available_at' => $availableAt, ]); - $result = $this->predis->zadd("queues:{$queue}:{$this->priority}", [json_encode($queueJob) => $availableAt->timestamp]); + try { + $result = $this->predis->zadd("queues:{$queue}:{$this->priority}", [json_encode($queueJob) => $availableAt->timestamp]); + } catch (Throwable $e) { + return QueuePushResult::failure('Unexpected Redis error: ' . $e->getMessage()); + } finally { + $this->priority = $this->delay = null; + } $this->priority = $this->delay = null; - return $result > 0 ? $jobId : null; + return $result > 0 + ? QueuePushResult::success($jobId) + : QueuePushResult::failure('Job already exists in the queue.'); } /** diff --git a/src/Handlers/RedisHandler.php b/src/Handlers/RedisHandler.php index 66d2050..4676436 100644 --- a/src/Handlers/RedisHandler.php +++ b/src/Handlers/RedisHandler.php @@ -22,6 +22,7 @@ use CodeIgniter\Queue\Interfaces\QueueInterface; use CodeIgniter\Queue\Payloads\Payload; use CodeIgniter\Queue\Payloads\PayloadMetadata; +use CodeIgniter\Queue\QueuePushResult; use Redis; use RedisException; use Throwable; @@ -76,14 +77,14 @@ public function name(): string * * @throws RedisException */ - public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): ?string + public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult { $this->validateJobAndPriority($queue, $job); helper('text'); $availableAt = Time::now()->addSeconds($this->delay ?? 0); - $jobId = random_string('numeric', 16); + $jobId = (int) random_string('numeric', 16); $queueJob = new QueueJob([ 'id' => $jobId, @@ -95,11 +96,21 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $ 'available_at' => $availableAt, ]); - $result = (int) $this->redis->zAdd("queues:{$queue}:{$this->priority}", $availableAt->timestamp, json_encode($queueJob)); + try { + $result = $this->redis->zAdd("queues:{$queue}:{$this->priority}", $availableAt->timestamp, json_encode($queueJob)); + } catch (Throwable $e) { + return QueuePushResult::failure('Unexpected Redis error: ' . $e->getMessage()); + } finally { + $this->priority = $this->delay = null; + } - $this->priority = $this->delay = null; + if ($result === false) { + return QueuePushResult::failure('Failed to add job to Redis.'); + } - return $result > 0 ? $jobId : null; + return (int) $result > 0 + ? QueuePushResult::success($jobId) + : QueuePushResult::failure('Job already exists in the queue.'); } /** diff --git a/src/Payloads/ChainBuilder.php b/src/Payloads/ChainBuilder.php index 34de95e..772e376 100644 --- a/src/Payloads/ChainBuilder.php +++ b/src/Payloads/ChainBuilder.php @@ -14,6 +14,7 @@ namespace CodeIgniter\Queue\Payloads; use CodeIgniter\Queue\Handlers\BaseHandler; +use CodeIgniter\Queue\QueuePushResult; class ChainBuilder { @@ -44,10 +45,10 @@ public function push(string $queue, string $jobName, array $data = []): ChainEle /** * Dispatch the chain of jobs */ - public function dispatch(): ?string + public function dispatch(): QueuePushResult { if ($this->payloads->count() === 0) { - return null; + return QueuePushResult::failure('No jobs to dispatch.'); } $current = $this->payloads->shift(); diff --git a/src/QueuePushResult.php b/src/QueuePushResult.php new file mode 100644 index 0000000..91d9a56 --- /dev/null +++ b/src/QueuePushResult.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Queue; + +class QueuePushResult +{ + public function __construct( + protected readonly bool $success, + protected readonly ?int $jobId = null, + protected readonly ?string $error = null, + ) { + } + + public static function success(int $jobId): self + { + return new self(true, $jobId); + } + + public static function failure(?string $error = null): self + { + return new self(false, null, $error); + } + + public function getStatus(): bool + { + return $this->success; + } + + public function getJobId(): ?int + { + return $this->jobId; + } + + public function getError(): ?string + { + return $this->error; + } +} diff --git a/tests/DatabaseHandlerTest.php b/tests/DatabaseHandlerTest.php index 1ddc7c6..f189f78 100644 --- a/tests/DatabaseHandlerTest.php +++ b/tests/DatabaseHandlerTest.php @@ -85,7 +85,7 @@ public function testPush(): void $handler = new DatabaseHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]), @@ -103,7 +103,7 @@ public function testPushWithPriority(): void $handler = new DatabaseHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]), @@ -122,7 +122,7 @@ public function testPushAndPopWithPriority(): void $handler = new DatabaseHandler($this->config); $result = $handler->push('queue', 'success', ['key1' => 'value1']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key1' => 'value1'], 'metadata' => []]), @@ -132,7 +132,7 @@ public function testPushAndPopWithPriority(): void $result = $handler->setPriority('high')->push('queue', 'success', ['key2' => 'value2']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode(['job' => 'success', 'data' => ['key2' => 'value2'], 'metadata' => []]), @@ -161,7 +161,7 @@ public function testPushWithDelay(): void $handler = new DatabaseHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $availableAt = 1703859376; @@ -188,7 +188,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ @@ -221,7 +221,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ diff --git a/tests/Payloads/ChainBuilderTest.php b/tests/Payloads/ChainBuilderTest.php index 8ab52ea..6aa91ba 100644 --- a/tests/Payloads/ChainBuilderTest.php +++ b/tests/Payloads/ChainBuilderTest.php @@ -63,7 +63,7 @@ public function testChainWithSingleJob(): void $chain->push('queue', 'success', ['key' => 'value']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ @@ -84,7 +84,7 @@ public function testEmptyChain(): void // No jobs added }); - $this->assertNull($result); + $this->assertFalse($result->getStatus()); $this->seeInDatabase('queue_jobs', []); } @@ -99,7 +99,7 @@ public function testMultipleDifferentQueues(): void ->push('queue2', 'success', ['key2' => 'value2']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue1', 'payload' => json_encode([ @@ -132,7 +132,7 @@ public function testChainWithManyJobs(): void ->push('queue', 'success', ['key3' => 'value3']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $this->seeInDatabase('queue_jobs', [ 'queue' => 'queue', 'payload' => json_encode([ diff --git a/tests/PredisHandlerTest.php b/tests/PredisHandlerTest.php index 17b8e90..05d79d0 100644 --- a/tests/PredisHandlerTest.php +++ b/tests/PredisHandlerTest.php @@ -72,7 +72,7 @@ public function testPush(): void $handler = new PredisHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:low')); @@ -92,7 +92,7 @@ public function testPushWithPriority(): void $handler = new PredisHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:high')); @@ -114,7 +114,7 @@ public function testPushWithDelay(): void $handler = new PredisHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue-delay:default')); @@ -140,7 +140,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $predis = self::getPrivateProperty($handler, 'predis'); $this->assertSame(1, $predis->zcard('queues:queue:low')); @@ -180,7 +180,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $predis = self::getPrivateProperty($handler, 'predis'); // Should be in high priority queue diff --git a/tests/QueuePushResultTest.php b/tests/QueuePushResultTest.php new file mode 100644 index 0000000..f5a6dfa --- /dev/null +++ b/tests/QueuePushResultTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests; + +use CodeIgniter\Queue\QueuePushResult; +use Tests\Support\TestCase; + +/** + * @internal + */ +final class QueuePushResultTest extends TestCase +{ + public function testConstructorSuccess(): void + { + $result = new QueuePushResult(true, 123456, null); + + $this->assertTrue($result->getStatus()); + $this->assertSame(123456, $result->getJobId()); + $this->assertNull($result->getError()); + } + + public function testConstructorFailure(): void + { + $result = new QueuePushResult(false, null, 'Something went wrong'); + + $this->assertFalse($result->getStatus()); + $this->assertNull($result->getJobId()); + $this->assertSame('Something went wrong', $result->getError()); + } + + public function testStaticSuccess(): void + { + $result = QueuePushResult::success(999888); + + $this->assertTrue($result->getStatus()); + $this->assertSame(999888, $result->getJobId()); + $this->assertNull($result->getError()); + } + + public function testStaticFailure(): void + { + $result = QueuePushResult::failure('Redis error'); + + $this->assertFalse($result->getStatus()); + $this->assertNull($result->getJobId()); + $this->assertSame('Redis error', $result->getError()); + } + + public function testStaticFailureWithoutError(): void + { + $result = QueuePushResult::failure(); + + $this->assertFalse($result->getStatus()); + $this->assertNull($result->getJobId()); + $this->assertNull($result->getError()); + } +} diff --git a/tests/RedisHandlerTest.php b/tests/RedisHandlerTest.php index 82a2066..7707cd4 100644 --- a/tests/RedisHandlerTest.php +++ b/tests/RedisHandlerTest.php @@ -69,7 +69,7 @@ public function testPush(): void $handler = new RedisHandler($this->config); $result = $handler->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:low')); @@ -86,7 +86,7 @@ public function testPushWithPriority(): void $handler = new RedisHandler($this->config); $result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:high')); @@ -108,7 +108,7 @@ public function testPushWithDelay(): void $handler = new RedisHandler($this->config); $result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue-delay:default')); @@ -134,7 +134,7 @@ public function testChain(): void ->push('queue', 'success', ['key2' => 'value2']); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $redis = self::getPrivateProperty($handler, 'redis'); $this->assertSame(1, $redis->zCard('queues:queue:low')); @@ -174,7 +174,7 @@ public function testChainWithPriorityAndDelay(): void ->setDelay(120); }); - $this->assertNotNull($result); + $this->assertTrue($result->getStatus()); $redis = self::getPrivateProperty($handler, 'redis'); // Should be in high priority queue From 38efafc436d7294ff1d0c7b663e2591477c32e72 Mon Sep 17 00:00:00 2001 From: michalsn Date: Sun, 8 Jun 2025 18:20:51 +0200 Subject: [PATCH 4/4] add some PHPDocs to QueuePushResult class --- src/QueuePushResult.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/QueuePushResult.php b/src/QueuePushResult.php index 91d9a56..efe7456 100644 --- a/src/QueuePushResult.php +++ b/src/QueuePushResult.php @@ -13,6 +13,9 @@ namespace CodeIgniter\Queue; +/** + * Represents the result of a queue push operation. + */ class QueuePushResult { public function __construct( @@ -22,26 +25,41 @@ public function __construct( ) { } + /** + * Creates a successful push result. + */ public static function success(int $jobId): self { return new self(true, $jobId); } + /** + * Creates a failed push result. + */ public static function failure(?string $error = null): self { return new self(false, null, $error); } + /** + * Returns whether the push operation was successful. + */ public function getStatus(): bool { return $this->success; } + /** + * Returns the job ID if the push was successful, null otherwise. + */ public function getJobId(): ?int { return $this->jobId; } + /** + * Returns the error message if the push failed, null otherwise. + */ public function getError(): ?string { return $this->error;