Skip to content

Commit ecb790c

Browse files
authored
feat: Queue::push() to return QueuePushResult instead of boolean (#62)
* feat: return jobID after push instead of the bool value * fix phpcpd * feat: return QueuePushResult from push() instead of bool * add some PHPDocs to QueuePushResult class
1 parent 39f0a8b commit ecb790c

13 files changed

+217
-41
lines changed

docs/basic-usage.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ service('queue')->push('emails', 'email', ['message' => 'Email message goes here
160160

161161
We will be pushing `email` job to the `emails` queue.
162162

163+
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:
164+
165+
- `getStatus()`: Indicates whether the job was successfully added to the queue.
166+
- `getJobId()`: Returns the ID of the job that was added to the queue.
167+
- `getError()`: Returns any error that occurred if the job was not added.
168+
163169
### Sending chained jobs to the queue
164170

165171
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) {
172178
});
173179
```
174180

175-
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.
181+
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.
176182
The `email` job will be executed only if the `generate-report` job was successful.
177183

184+
As with the `push()` method, calling the `chain()` method also returns a `QueuePushResult` object.
185+
178186
### Consuming the queue
179187

180188
Since we sent our sample job to queue `emails`, then we need to run the worker with the appropriate queue:

src/Handlers/BaseHandler.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use CodeIgniter\Queue\Models\QueueJobFailedModel;
2323
use CodeIgniter\Queue\Payloads\ChainBuilder;
2424
use CodeIgniter\Queue\Payloads\PayloadMetadata;
25+
use CodeIgniter\Queue\QueuePushResult;
2526
use CodeIgniter\Queue\Traits\HasQueueValidation;
2627
use ReflectionException;
2728
use Throwable;
@@ -39,7 +40,7 @@ abstract class BaseHandler
3940

4041
abstract public function name(): string;
4142

42-
abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool;
43+
abstract public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult;
4344

4445
abstract public function pop(string $queue, array $priorities): ?QueueJob;
4546

@@ -153,7 +154,7 @@ public function setPriority(string $priority): static
153154
*
154155
* @param Closure $callback Chain definition callback
155156
*/
156-
public function chain(Closure $callback): bool
157+
public function chain(Closure $callback): QueuePushResult
157158
{
158159
$chainBuilder = new ChainBuilder($this);
159160
$callback($chainBuilder);

src/Handlers/DatabaseHandler.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use CodeIgniter\Queue\Models\QueueJobModel;
2222
use CodeIgniter\Queue\Payloads\Payload;
2323
use CodeIgniter\Queue\Payloads\PayloadMetadata;
24+
use CodeIgniter\Queue\QueuePushResult;
2425
use ReflectionException;
2526
use Throwable;
2627

@@ -44,10 +45,8 @@ public function name(): string
4445

4546
/**
4647
* Add job to the queue.
47-
*
48-
* @throws ReflectionException
4948
*/
50-
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool
49+
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult
5150
{
5251
$this->validateJobAndPriority($queue, $job);
5352

@@ -62,7 +61,17 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $
6261

6362
$this->priority = $this->delay = null;
6463

65-
return $this->jobModel->insert($queueJob, false);
64+
try {
65+
$jobId = $this->jobModel->insert($queueJob);
66+
} catch (Throwable $e) {
67+
return QueuePushResult::failure($e->getMessage());
68+
}
69+
70+
if ($jobId === 0) {
71+
return QueuePushResult::failure('Failed to insert job into the database.');
72+
}
73+
74+
return QueuePushResult::success($jobId);
6675
}
6776

6877
/**

src/Handlers/PredisHandler.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use CodeIgniter\Queue\Interfaces\QueueInterface;
2323
use CodeIgniter\Queue\Payloads\Payload;
2424
use CodeIgniter\Queue\Payloads\PayloadMetadata;
25+
use CodeIgniter\Queue\QueuePushResult;
2526
use Exception;
2627
use Predis\Client;
2728
use Throwable;
@@ -59,16 +60,17 @@ public function name(): string
5960
/**
6061
* Add job to the queue.
6162
*/
62-
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool
63+
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult
6364
{
6465
$this->validateJobAndPriority($queue, $job);
6566

6667
helper('text');
6768

69+
$jobId = (int) random_string('numeric', 16);
6870
$availableAt = Time::now()->addSeconds($this->delay ?? 0);
6971

7072
$queueJob = new QueueJob([
71-
'id' => random_string('numeric', 16),
73+
'id' => $jobId,
7274
'queue' => $queue,
7375
'payload' => new Payload($job, $data, $metadata),
7476
'priority' => $this->priority,
@@ -77,11 +79,19 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $
7779
'available_at' => $availableAt,
7880
]);
7981

80-
$result = $this->predis->zadd("queues:{$queue}:{$this->priority}", [json_encode($queueJob) => $availableAt->timestamp]);
82+
try {
83+
$result = $this->predis->zadd("queues:{$queue}:{$this->priority}", [json_encode($queueJob) => $availableAt->timestamp]);
84+
} catch (Throwable $e) {
85+
return QueuePushResult::failure('Unexpected Redis error: ' . $e->getMessage());
86+
} finally {
87+
$this->priority = $this->delay = null;
88+
}
8189

8290
$this->priority = $this->delay = null;
8391

84-
return $result > 0;
92+
return $result > 0
93+
? QueuePushResult::success($jobId)
94+
: QueuePushResult::failure('Job already exists in the queue.');
8595
}
8696

8797
/**

src/Handlers/RedisHandler.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use CodeIgniter\Queue\Interfaces\QueueInterface;
2323
use CodeIgniter\Queue\Payloads\Payload;
2424
use CodeIgniter\Queue\Payloads\PayloadMetadata;
25+
use CodeIgniter\Queue\QueuePushResult;
2526
use Redis;
2627
use RedisException;
2728
use Throwable;
@@ -76,16 +77,17 @@ public function name(): string
7677
*
7778
* @throws RedisException
7879
*/
79-
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): bool
80+
public function push(string $queue, string $job, array $data, ?PayloadMetadata $metadata = null): QueuePushResult
8081
{
8182
$this->validateJobAndPriority($queue, $job);
8283

8384
helper('text');
8485

8586
$availableAt = Time::now()->addSeconds($this->delay ?? 0);
87+
$jobId = (int) random_string('numeric', 16);
8688

8789
$queueJob = new QueueJob([
88-
'id' => random_string('numeric', 16),
90+
'id' => $jobId,
8991
'queue' => $queue,
9092
'payload' => new Payload($job, $data, $metadata),
9193
'priority' => $this->priority,
@@ -94,11 +96,21 @@ public function push(string $queue, string $job, array $data, ?PayloadMetadata $
9496
'available_at' => $availableAt,
9597
]);
9698

97-
$result = (int) $this->redis->zAdd("queues:{$queue}:{$this->priority}", $availableAt->timestamp, json_encode($queueJob));
99+
try {
100+
$result = $this->redis->zAdd("queues:{$queue}:{$this->priority}", $availableAt->timestamp, json_encode($queueJob));
101+
} catch (Throwable $e) {
102+
return QueuePushResult::failure('Unexpected Redis error: ' . $e->getMessage());
103+
} finally {
104+
$this->priority = $this->delay = null;
105+
}
98106

99-
$this->priority = $this->delay = null;
107+
if ($result === false) {
108+
return QueuePushResult::failure('Failed to add job to Redis.');
109+
}
100110

101-
return $result > 0;
111+
return (int) $result > 0
112+
? QueuePushResult::success($jobId)
113+
: QueuePushResult::failure('Job already exists in the queue.');
102114
}
103115

104116
/**

src/Payloads/ChainBuilder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace CodeIgniter\Queue\Payloads;
1515

1616
use CodeIgniter\Queue\Handlers\BaseHandler;
17+
use CodeIgniter\Queue\QueuePushResult;
1718

1819
class ChainBuilder
1920
{
@@ -44,10 +45,10 @@ public function push(string $queue, string $jobName, array $data = []): ChainEle
4445
/**
4546
* Dispatch the chain of jobs
4647
*/
47-
public function dispatch(): bool
48+
public function dispatch(): QueuePushResult
4849
{
4950
if ($this->payloads->count() === 0) {
50-
return true;
51+
return QueuePushResult::failure('No jobs to dispatch.');
5152
}
5253

5354
$current = $this->payloads->shift();

src/QueuePushResult.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter Queue.
7+
*
8+
* (c) CodeIgniter Foundation <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\Queue;
15+
16+
/**
17+
* Represents the result of a queue push operation.
18+
*/
19+
class QueuePushResult
20+
{
21+
public function __construct(
22+
protected readonly bool $success,
23+
protected readonly ?int $jobId = null,
24+
protected readonly ?string $error = null,
25+
) {
26+
}
27+
28+
/**
29+
* Creates a successful push result.
30+
*/
31+
public static function success(int $jobId): self
32+
{
33+
return new self(true, $jobId);
34+
}
35+
36+
/**
37+
* Creates a failed push result.
38+
*/
39+
public static function failure(?string $error = null): self
40+
{
41+
return new self(false, null, $error);
42+
}
43+
44+
/**
45+
* Returns whether the push operation was successful.
46+
*/
47+
public function getStatus(): bool
48+
{
49+
return $this->success;
50+
}
51+
52+
/**
53+
* Returns the job ID if the push was successful, null otherwise.
54+
*/
55+
public function getJobId(): ?int
56+
{
57+
return $this->jobId;
58+
}
59+
60+
/**
61+
* Returns the error message if the push failed, null otherwise.
62+
*/
63+
public function getError(): ?string
64+
{
65+
return $this->error;
66+
}
67+
}

tests/DatabaseHandlerTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public function testPush(): void
8585
$handler = new DatabaseHandler($this->config);
8686
$result = $handler->push('queue', 'success', ['key' => 'value']);
8787

88-
$this->assertTrue($result);
88+
$this->assertTrue($result->getStatus());
8989
$this->seeInDatabase('queue_jobs', [
9090
'queue' => 'queue',
9191
'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]),
@@ -103,7 +103,7 @@ public function testPushWithPriority(): void
103103
$handler = new DatabaseHandler($this->config);
104104
$result = $handler->setPriority('high')->push('queue', 'success', ['key' => 'value']);
105105

106-
$this->assertTrue($result);
106+
$this->assertTrue($result->getStatus());
107107
$this->seeInDatabase('queue_jobs', [
108108
'queue' => 'queue',
109109
'payload' => json_encode(['job' => 'success', 'data' => ['key' => 'value'], 'metadata' => []]),
@@ -122,7 +122,7 @@ public function testPushAndPopWithPriority(): void
122122
$handler = new DatabaseHandler($this->config);
123123
$result = $handler->push('queue', 'success', ['key1' => 'value1']);
124124

125-
$this->assertTrue($result);
125+
$this->assertTrue($result->getStatus());
126126
$this->seeInDatabase('queue_jobs', [
127127
'queue' => 'queue',
128128
'payload' => json_encode(['job' => 'success', 'data' => ['key1' => 'value1'], 'metadata' => []]),
@@ -132,7 +132,7 @@ public function testPushAndPopWithPriority(): void
132132

133133
$result = $handler->setPriority('high')->push('queue', 'success', ['key2' => 'value2']);
134134

135-
$this->assertTrue($result);
135+
$this->assertTrue($result->getStatus());
136136
$this->seeInDatabase('queue_jobs', [
137137
'queue' => 'queue',
138138
'payload' => json_encode(['job' => 'success', 'data' => ['key2' => 'value2'], 'metadata' => []]),
@@ -161,7 +161,7 @@ public function testPushWithDelay(): void
161161
$handler = new DatabaseHandler($this->config);
162162
$result = $handler->setDelay(MINUTE)->push('queue-delay', 'success', ['key' => 'value']);
163163

164-
$this->assertTrue($result);
164+
$this->assertTrue($result->getStatus());
165165

166166
$availableAt = 1703859376;
167167

@@ -188,7 +188,7 @@ public function testChain(): void
188188
->push('queue', 'success', ['key2' => 'value2']);
189189
});
190190

191-
$this->assertTrue($result);
191+
$this->assertTrue($result->getStatus());
192192
$this->seeInDatabase('queue_jobs', [
193193
'queue' => 'queue',
194194
'payload' => json_encode([
@@ -221,7 +221,7 @@ public function testChainWithPriorityAndDelay(): void
221221
->setDelay(120);
222222
});
223223

224-
$this->assertTrue($result);
224+
$this->assertTrue($result->getStatus());
225225
$this->seeInDatabase('queue_jobs', [
226226
'queue' => 'queue',
227227
'payload' => json_encode([

tests/Payloads/ChainBuilderTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function testChainWithSingleJob(): void
6363
$chain->push('queue', 'success', ['key' => 'value']);
6464
});
6565

66-
$this->assertTrue($result);
66+
$this->assertTrue($result->getStatus());
6767
$this->seeInDatabase('queue_jobs', [
6868
'queue' => 'queue',
6969
'payload' => json_encode([
@@ -84,7 +84,7 @@ public function testEmptyChain(): void
8484
// No jobs added
8585
});
8686

87-
$this->assertTrue($result);
87+
$this->assertFalse($result->getStatus());
8888
$this->seeInDatabase('queue_jobs', []);
8989
}
9090

@@ -99,7 +99,7 @@ public function testMultipleDifferentQueues(): void
9999
->push('queue2', 'success', ['key2' => 'value2']);
100100
});
101101

102-
$this->assertTrue($result);
102+
$this->assertTrue($result->getStatus());
103103
$this->seeInDatabase('queue_jobs', [
104104
'queue' => 'queue1',
105105
'payload' => json_encode([
@@ -132,7 +132,7 @@ public function testChainWithManyJobs(): void
132132
->push('queue', 'success', ['key3' => 'value3']);
133133
});
134134

135-
$this->assertTrue($result);
135+
$this->assertTrue($result->getStatus());
136136
$this->seeInDatabase('queue_jobs', [
137137
'queue' => 'queue',
138138
'payload' => json_encode([

0 commit comments

Comments
 (0)