Skip to content

Commit 088523a

Browse files
authored
Merge pull request #12 from michalsn/type-fixes
refactor: fix type inconsistency and more
2 parents 6b9699c + 96548ca commit 088523a

11 files changed

Lines changed: 104 additions & 63 deletions

File tree

phpstan.neon.dist

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,13 @@ parameters:
88
- vendor/codeigniter4/framework/system/Test/bootstrap.php
99
excludePaths:
1010
ignoreErrors:
11-
-
12-
message: '#Cannot use \+\+ on array\|bool\|float\|int\|object\|string\|null.#'
13-
paths:
14-
- src/Commands/QueueWork.php
15-
-
16-
message: '#Variable \$config on left side of \?\?\= always exists and is not nullable.#'
17-
paths:
18-
- src/Config/Services.php
19-
-
20-
message: '#Call to an undefined method CodeIgniter\\Queue\\Handlers\\BaseHandler::push\(\).#'
21-
paths:
22-
- src/Handlers/BaseHandler.php
2311
-
2412
message: '#Call to deprecated function random_string\(\):#'
2513
paths:
2614
- src/Handlers/RedisHandler.php
2715
- src/Handlers/PredisHandler.php
28-
-
29-
message: '#Cannot access property \$timestamp on array\|bool\|float\|int\|object\|string.#'
30-
paths:
31-
- tests/_support/Database/Seeds/TestRedisQueueSeeder.php
3216
-
3317
message: '#Access to an undefined property CodeIgniter\\I18n\\Time::\$timestamp.#'
34-
paths:
35-
- src/Handlers/BaseHandler.php
36-
- src/Handlers/DatabaseHandler.php
37-
- src/Handlers/RedisHandler.php
38-
- src/Handlers/PredisHandler.php
39-
- src/Models/QueueJobModel.php
40-
- tests/RedisHandlerTest.php
41-
- tests/PredisHandlerTest.php
4218
-
4319
message: '#Call to an undefined method CodeIgniter\\Queue\\Models\\QueueJobFailedModel::affectedRows\(\).#'
4420
paths:
@@ -47,22 +23,6 @@ parameters:
4723
message: '#Call to an undefined method CodeIgniter\\Queue\\Models\\QueueJobFailedModel::truncate\(\).#'
4824
paths:
4925
- src/Handlers/BaseHandler.php
50-
-
51-
message: '#Parameter \#3 \$tries of method CodeIgniter\\Queue\\Commands\\QueueWork::handleWork\(\) expects int\|null, string\|true\|null given.#'
52-
paths:
53-
- src/Commands/QueueWork.php
54-
-
55-
message: '#Parameter \#4 \$retryAfter of method CodeIgniter\\Queue\\Commands\\QueueWork::handleWork\(\) expects int\|null, string\|true\|null given.#'
56-
paths:
57-
- src/Commands/QueueWork.php
58-
-
59-
message: '#Expression on left side of \?\? is not nullable.#'
60-
paths:
61-
- src/Commands/QueueWork.php
62-
-
63-
message: '#Variable \$job might not be defined.#'
64-
paths:
65-
- src/Commands/QueueWork.php
6626
universalObjectCratesClasses:
6727
- CodeIgniter\Entity
6828
- CodeIgniter\Entity\Entity

src/Commands/QueueWork.php

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,33 @@ public function run(array $params)
7979
$stopWhenEmpty = false;
8080
$waiting = false;
8181

82-
// Read params
82+
// Read queue name from params
8383
if (! $queue = array_shift($params)) {
8484
CLI::error('The queueName is not specified.');
8585

8686
return EXIT_ERROR;
8787
}
8888

8989
// Read options
90-
$sleep = $params['sleep'] ?? CLI::getOption('sleep') ?? 10;
91-
$rest = $params['rest'] ?? CLI::getOption('rest') ?? 0;
92-
$maxJobs = $params['max-jobs'] ?? CLI::getOption('max-jobs') ?? 0;
93-
$maxTime = $params['max-time'] ?? CLI::getOption('max-time') ?? 0;
94-
$memory = $params['memory'] ?? CLI::getOption('memory') ?? 128;
95-
$priority = $params['priority'] ?? CLI::getOption('priority') ?? $config->getQueuePriorities($queue) ?? 'default';
96-
$tries = $params['tries'] ?? CLI::getOption('tries');
97-
$retryAfter = $params['retry-after'] ?? CLI::getOption('retry-after');
98-
$countJobs = 0;
90+
[
91+
$error,
92+
$sleep,
93+
$rest,
94+
$maxJobs,
95+
$maxTime,
96+
$memory,
97+
$priority,
98+
$tries,
99+
$retryAfter
100+
] = $this->readOptions($params, $config, $queue);
101+
102+
if ($error !== null) {
103+
CLI::write($error, 'red');
104+
105+
return EXIT_ERROR;
106+
}
107+
108+
$countJobs = 0;
99109

100110
if (array_key_exists('stop-when-empty', $params) || CLI::getOption('stop-when-empty')) {
101111
$stopWhenEmpty = true;
@@ -111,7 +121,7 @@ public function run(array $params)
111121

112122
CLI::write(PHP_EOL);
113123

114-
$priority = array_map('trim', explode(',', $priority));
124+
$priority = array_map('trim', explode(',', (string) $priority));
115125

116126
while (true) {
117127
$work = service('queue')->pop($queue, $priority);
@@ -175,6 +185,42 @@ public function run(array $params)
175185
}
176186
}
177187

188+
private function readOptions(array $params, QueueConfig $config, string $queue): array
189+
{
190+
$options = [
191+
'error' => null,
192+
'sleep' => $params['sleep'] ?? CLI::getOption('sleep') ?? 10,
193+
'rest' => $params['rest'] ?? CLI::getOption('rest') ?? 0,
194+
'maxJobs' => $params['max-jobs'] ?? CLI::getOption('max-jobs') ?? 0,
195+
'maxTime' => $params['max-time'] ?? CLI::getOption('max-time') ?? 0,
196+
'memory' => $params['memory'] ?? CLI::getOption('memory') ?? 128,
197+
'priority' => $params['priority'] ?? CLI::getOption('priority') ?? $config->getQueuePriorities($queue) ?? 'default',
198+
'tries' => $params['tries'] ?? CLI::getOption('tries'),
199+
'retryAfter' => $params['retry-after'] ?? CLI::getOption('retry-after'),
200+
];
201+
202+
// Options that, being defined, cannot be `true`
203+
$keys = ['sleep', 'rest', 'maxJobs', 'maxTime', 'memory', 'priority', 'tries', 'retyAfter'];
204+
205+
foreach ($keys as $key) {
206+
if ($options[$key] === true) {
207+
$options['error'] = sprintf('Option: "-%s" must have a defined value.', $key);
208+
209+
return array_values($options);
210+
}
211+
}
212+
// Options that, being defined, have to be `int`
213+
$keys = array_diff($keys, ['priority']);
214+
215+
foreach ($keys as $key) {
216+
if ($options[$key] !== null && ! is_int($options[$key])) {
217+
$options[$key] = (int) $options[$key];
218+
}
219+
}
220+
221+
return array_values($options);
222+
}
223+
178224
private function handleWork(QueueJob $work, QueueConfig $config, ?int $tries, ?int $retryAfter): void
179225
{
180226
timer()->start('work');
@@ -190,7 +236,7 @@ private function handleWork(QueueJob $work, QueueConfig $config, ?int $tries, ?i
190236

191237
CLI::write('The processing of this job was successful', 'green');
192238
} catch (Throwable $err) {
193-
if (isset($job) && ++$work->attempts < $tries ?? $job->getTries()) {
239+
if (isset($job) && ++$work->attempts < ($tries ?? $job->getTries())) {
194240
// Schedule for later
195241
service('queue')->later($work, $retryAfter ?? $job->getRetryAfter());
196242
} else {

src/Config/Queue.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use CodeIgniter\Queue\Handlers\DatabaseHandler;
88
use CodeIgniter\Queue\Handlers\PredisHandler;
99
use CodeIgniter\Queue\Handlers\RedisHandler;
10+
use CodeIgniter\Queue\Interfaces\JobInterface;
11+
use CodeIgniter\Queue\Interfaces\QueueInterface;
1012

1113
class Queue extends BaseConfig
1214
{
@@ -17,6 +19,8 @@ class Queue extends BaseConfig
1719

1820
/**
1921
* Available handlers.
22+
*
23+
* @var array<string, class-string<QueueInterface>>
2024
*/
2125
public array $handlers = [
2226
'database' => DatabaseHandler::class,
@@ -81,6 +85,8 @@ class Queue extends BaseConfig
8185

8286
/**
8387
* Your jobs handlers.
88+
*
89+
* @var array<string, class-string<JobInterface>>
8490
*/
8591
public array $jobHandlers = [];
8692

@@ -95,6 +101,8 @@ public function __construct()
95101

96102
/**
97103
* Resolve job class name.
104+
*
105+
* @return class-string<JobInterface>
98106
*/
99107
public function resolveJobClass(string $name): string
100108
{

src/Config/Services.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static function queue(?QueueConfig $config = null, $getShared = true): Qu
1515
return static::getSharedInstance('queue', $config);
1616
}
1717

18-
/** @var QueueConfig $config */
18+
/** @var QueueConfig|null $config */
1919
$config ??= config('Queue');
2020

2121
return (new Queue($config))->init();

src/Entities/QueueJob.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@
33
namespace CodeIgniter\Queue\Entities;
44

55
use CodeIgniter\Entity\Entity;
6+
use CodeIgniter\I18n\Time;
67

8+
/**
9+
* @property int $attempts
10+
* @property Time $available_at
11+
* @property Time $created_at
12+
* @property int $id
13+
* @property array $payload
14+
* @property string $priority
15+
* @property string $queue
16+
* @property int $status
17+
*/
718
class QueueJob extends Entity
819
{
920
protected $dates = ['available_at', 'created_at'];

src/Handlers/BaseHandler.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ abstract class BaseHandler
1919
protected QueueConfig $config;
2020
protected ?string $priority = null;
2121

22+
abstract public function push(string $queue, string $job, array $data): bool;
23+
24+
abstract public function pop(string $queue, array $priorities): ?QueueJob;
25+
26+
abstract public function later(QueueJob $queueJob, int $seconds): bool;
27+
28+
abstract public function failed(QueueJob $queueJob, Throwable $err, bool $keepJob): bool;
29+
30+
abstract public function done(QueueJob $queueJob, bool $keepJob): bool;
31+
32+
abstract public function clear(?string $queue = null): bool;
33+
2234
/**
2335
* Set priority for job queue.
2436
*/

src/Handlers/PredisHandler.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public function pop(string $queue, array $priorities): ?QueueJob
8080
$queueJob->status = Status::RESERVED->value;
8181
$queueJob->syncOriginal();
8282

83-
$this->predis->hset("queues:{$queue}::reserved", $queueJob->id, json_encode($queueJob));
83+
$this->predis->hset("queues:{$queue}::reserved", (string) $queueJob->id, json_encode($queueJob));
8484

8585
return $queueJob;
8686
}
@@ -94,7 +94,7 @@ public function later(QueueJob $queueJob, int $seconds): bool
9494
$queueJob->available_at = Time::now()->addSeconds($seconds)->timestamp;
9595

9696
if ($result = $this->predis->zadd("queues:{$queueJob->queue}:{$queueJob->priority}", [json_encode($queueJob) => $queueJob->available_at->timestamp])) {
97-
$this->predis->hdel("queues:{$queueJob->queue}::reserved", $queueJob->id);
97+
$this->predis->hdel("queues:{$queueJob->queue}::reserved", [$queueJob->id]);
9898
}
9999

100100
return $result > 0;
@@ -109,7 +109,7 @@ public function failed(QueueJob $queueJob, Throwable $err, bool $keepJob): bool
109109
$this->logFailed($queueJob, $err);
110110
}
111111

112-
return (bool) $this->predis->hdel("queues:{$queueJob->queue}::reserved", $queueJob->id);
112+
return (bool) $this->predis->hdel("queues:{$queueJob->queue}::reserved", [$queueJob->id]);
113113
}
114114

115115
/**
@@ -122,7 +122,7 @@ public function done(QueueJob $queueJob, bool $keepJob): bool
122122
$this->predis->lpush("queues:{$queueJob->queue}::done", [json_encode($queueJob)]);
123123
}
124124

125-
return (bool) $this->predis->hdel("queues:{$queueJob->queue}::reserved", $queueJob->id);
125+
return (bool) $this->predis->hdel("queues:{$queueJob->queue}::reserved", [$queueJob->id]);
126126
}
127127

128128
/**

src/Handlers/RedisHandler.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function pop(string $queue, array $priorities): ?QueueJob
9999
$queueJob->status = Status::RESERVED->value;
100100
$queueJob->syncOriginal();
101101

102-
$this->redis->hSet("queues:{$queue}::reserved", $queueJob->id, json_encode($queueJob));
102+
$this->redis->hSet("queues:{$queue}::reserved", (string) $queueJob->id, json_encode($queueJob));
103103

104104
return $queueJob;
105105
}
@@ -115,7 +115,7 @@ public function later(QueueJob $queueJob, int $seconds): bool
115115
$queueJob->available_at = Time::now()->addSeconds($seconds)->timestamp;
116116

117117
if ($result = (int) $this->redis->zAdd("queues:{$queueJob->queue}:{$queueJob->priority}", $queueJob->available_at->timestamp, json_encode($queueJob))) {
118-
$this->redis->hDel("queues:{$queueJob->queue}::reserved", $queueJob->id);
118+
$this->redis->hDel("queues:{$queueJob->queue}::reserved", (string) $queueJob->id);
119119
}
120120

121121
return $result > 0;
@@ -130,7 +130,7 @@ public function failed(QueueJob $queueJob, Throwable $err, bool $keepJob): bool
130130
$this->logFailed($queueJob, $err);
131131
}
132132

133-
return (bool) $this->redis->hDel("queues:{$queueJob->queue}::reserved", $queueJob->id);
133+
return (bool) $this->redis->hDel("queues:{$queueJob->queue}::reserved", (string) $queueJob->id);
134134
}
135135

136136
/**
@@ -145,7 +145,7 @@ public function done(QueueJob $queueJob, bool $keepJob): bool
145145
$this->redis->lPush("queues:{$queueJob->queue}::done", json_encode($queueJob));
146146
}
147147

148-
return (bool) $this->redis->hDel("queues:{$queueJob->queue}::reserved", $queueJob->id);
148+
return (bool) $this->redis->hDel("queues:{$queueJob->queue}::reserved", (string) $queueJob->id);
149149
}
150150

151151
/**

src/Interfaces/JobInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ interface JobInterface
77
public function __construct(array $data);
88

99
public function process();
10+
11+
public function getRetryAfter(): int;
12+
13+
public function getTries(): int;
1014
}

tests/_support/Database/Seeds/TestRedisQueueSeeder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function run(): void
4040
'attempts' => 0,
4141
'available_at' => 1_697_269_864,
4242
]);
43-
$redis->hSet("queues:{$jobQueue->queue}::reserved", $jobQueue->id, json_encode($jobQueue));
43+
$redis->hSet("queues:{$jobQueue->queue}::reserved", (string) $jobQueue->id, json_encode($jobQueue));
4444

4545
$jobQueue = new QueueJob([
4646
'id' => '1234567890654321',

0 commit comments

Comments
 (0)