13
13
14
14
namespace CodeIgniter \Queue \Handlers ;
15
15
16
+ use CodeIgniter \Autoloader \FileLocator ;
16
17
use CodeIgniter \Exceptions \CriticalError ;
17
18
use CodeIgniter \I18n \Time ;
18
19
use CodeIgniter \Queue \Config \Queue as QueueConfig ;
27
28
class RedisHandler extends BaseHandler implements QueueInterface
28
29
{
29
30
private readonly Redis $ redis ;
31
+ private readonly string $ luaScript ;
30
32
31
33
public function __construct (protected QueueConfig $ config )
32
34
{
@@ -48,6 +50,13 @@ public function __construct(protected QueueConfig $config)
48
50
if (isset ($ config ->redis ['prefix ' ]) && ! $ this ->redis ->setOption (Redis::OPT_PREFIX , $ config ->redis ['prefix ' ])) {
49
51
throw new CriticalError ('Queue: Redis setting prefix failed. ' );
50
52
}
53
+
54
+ $ locator = new FileLocator (service ('autoloader ' ));
55
+ $ luaScript = $ locator ->locateFile ('CodeIgniter\Queue\Lua\pop_task ' , null , 'lua ' );
56
+ if ($ luaScript === false ) {
57
+ throw new CriticalError ('Queue: LUA script for Redis is not available. ' );
58
+ }
59
+ $ this ->luaScript = file_get_contents ($ luaScript );
51
60
} catch (RedisException $ e ) {
52
61
throw new CriticalError ('Queue: RedisException occurred with message ( ' . $ e ->getMessage () . '). ' );
53
62
}
@@ -96,23 +105,23 @@ public function push(string $queue, string $job, array $data): bool
96
105
*/
97
106
public function pop (string $ queue , array $ priorities ): ?QueueJob
98
107
{
99
- $ tasks = [] ;
100
- $ now = Time:: now ()-> timestamp ;
101
-
102
- foreach ( $ priorities as $ priority ) {
103
- if ( $ tasks = $ this -> redis -> zRangeByScore ( " queues: { $ queue} : { $ priority }" , ' -inf ' , ( string ) $ now , [ ' limit ' => [ 0 , 1 ]])) {
104
- if ( $ this -> redis -> zRem ( " queues: { $ queue } : { $ priority }" , ... $ tasks )) {
105
- break ;
106
- }
107
- $ tasks = [];
108
- }
109
- }
108
+ $ now = Time:: now ()-> timestamp ;
109
+
110
+ // Prepare the arguments for the Lua script
111
+ $ args = [
112
+ ' queues: ' . $ queue, // KEYS[1]
113
+ $ now , // ARGV[2]
114
+ json_encode ( $ priorities ), // ARGV[3]
115
+ ];
116
+
117
+ // Execute the Lua script
118
+ $ task = $ this -> redis -> eval ( $ this -> luaScript , $ args , 1 );
110
119
111
- if ($ tasks === [] ) {
120
+ if ($ task === false ) {
112
121
return null ;
113
122
}
114
123
115
- $ queueJob = new QueueJob (json_decode ((string ) $ tasks [ 0 ] , true ));
124
+ $ queueJob = new QueueJob (json_decode ((string ) $ task , true ));
116
125
117
126
// Set the actual status as in DB.
118
127
$ queueJob ->status = Status::RESERVED ->value ;
0 commit comments