| 148 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
namespace Illuminate\Queue;
|
|
|
4 |
|
|
|
5 |
class LuaScripts
|
|
|
6 |
{
|
|
|
7 |
/**
|
|
|
8 |
* Get the Lua script for computing the size of queue.
|
|
|
9 |
*
|
|
|
10 |
* KEYS[1] - The name of the primary queue
|
|
|
11 |
* KEYS[2] - The name of the "delayed" queue
|
|
|
12 |
* KEYS[3] - The name of the "reserved" queue
|
|
|
13 |
*
|
|
|
14 |
* @return string
|
|
|
15 |
*/
|
|
|
16 |
public static function size()
|
|
|
17 |
{
|
|
|
18 |
return <<<'LUA'
|
|
|
19 |
return redis.call('llen', KEYS[1]) + redis.call('zcard', KEYS[2]) + redis.call('zcard', KEYS[3])
|
|
|
20 |
LUA;
|
|
|
21 |
}
|
|
|
22 |
|
|
|
23 |
/**
|
|
|
24 |
* Get the Lua script for pushing jobs onto the queue.
|
|
|
25 |
*
|
|
|
26 |
* KEYS[1] - The queue to push the job onto, for example: queues:foo
|
|
|
27 |
* KEYS[2] - The notification list for the queue we are pushing jobs onto, for example: queues:foo:notify
|
|
|
28 |
* ARGV[1] - The job payload
|
|
|
29 |
*
|
|
|
30 |
* @return string
|
|
|
31 |
*/
|
|
|
32 |
public static function push()
|
|
|
33 |
{
|
|
|
34 |
return <<<'LUA'
|
|
|
35 |
-- Push the job onto the queue...
|
|
|
36 |
redis.call('rpush', KEYS[1], ARGV[1])
|
|
|
37 |
-- Push a notification onto the "notify" queue...
|
|
|
38 |
redis.call('rpush', KEYS[2], 1)
|
|
|
39 |
LUA;
|
|
|
40 |
}
|
|
|
41 |
|
|
|
42 |
/**
|
|
|
43 |
* Get the Lua script for popping the next job off of the queue.
|
|
|
44 |
*
|
|
|
45 |
* KEYS[1] - The queue to pop jobs from, for example: queues:foo
|
|
|
46 |
* KEYS[2] - The queue to place reserved jobs on, for example: queues:foo:reserved
|
|
|
47 |
* KEYS[3] - The notify queue
|
|
|
48 |
* ARGV[1] - The time at which the reserved job will expire
|
|
|
49 |
*
|
|
|
50 |
* @return string
|
|
|
51 |
*/
|
|
|
52 |
public static function pop()
|
|
|
53 |
{
|
|
|
54 |
return <<<'LUA'
|
|
|
55 |
-- Pop the first job off of the queue...
|
|
|
56 |
local job = redis.call('lpop', KEYS[1])
|
|
|
57 |
local reserved = false
|
|
|
58 |
|
|
|
59 |
if(job ~= false) then
|
|
|
60 |
-- Increment the attempt count and place job on the reserved queue...
|
|
|
61 |
reserved = cjson.decode(job)
|
|
|
62 |
reserved['attempts'] = reserved['attempts'] + 1
|
|
|
63 |
reserved = cjson.encode(reserved)
|
|
|
64 |
redis.call('zadd', KEYS[2], ARGV[1], reserved)
|
|
|
65 |
redis.call('lpop', KEYS[3])
|
|
|
66 |
end
|
|
|
67 |
|
|
|
68 |
return {job, reserved}
|
|
|
69 |
LUA;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
/**
|
|
|
73 |
* Get the Lua script for releasing reserved jobs.
|
|
|
74 |
*
|
|
|
75 |
* KEYS[1] - The "delayed" queue we release jobs onto, for example: queues:foo:delayed
|
|
|
76 |
* KEYS[2] - The queue the jobs are currently on, for example: queues:foo:reserved
|
|
|
77 |
* ARGV[1] - The raw payload of the job to add to the "delayed" queue
|
|
|
78 |
* ARGV[2] - The UNIX timestamp at which the job should become available
|
|
|
79 |
*
|
|
|
80 |
* @return string
|
|
|
81 |
*/
|
|
|
82 |
public static function release()
|
|
|
83 |
{
|
|
|
84 |
return <<<'LUA'
|
|
|
85 |
-- Remove the job from the current queue...
|
|
|
86 |
redis.call('zrem', KEYS[2], ARGV[1])
|
|
|
87 |
|
|
|
88 |
-- Add the job onto the "delayed" queue...
|
|
|
89 |
redis.call('zadd', KEYS[1], ARGV[2], ARGV[1])
|
|
|
90 |
|
|
|
91 |
return true
|
|
|
92 |
LUA;
|
|
|
93 |
}
|
|
|
94 |
|
|
|
95 |
/**
|
|
|
96 |
* Get the Lua script to migrate expired jobs back onto the queue.
|
|
|
97 |
*
|
|
|
98 |
* KEYS[1] - The queue we are removing jobs from, for example: queues:foo:reserved
|
|
|
99 |
* KEYS[2] - The queue we are moving jobs to, for example: queues:foo
|
|
|
100 |
* KEYS[3] - The notification list for the queue we are moving jobs to, for example queues:foo:notify
|
|
|
101 |
* ARGV[1] - The current UNIX timestamp
|
|
|
102 |
*
|
|
|
103 |
* @return string
|
|
|
104 |
*/
|
|
|
105 |
public static function migrateExpiredJobs()
|
|
|
106 |
{
|
|
|
107 |
return <<<'LUA'
|
|
|
108 |
-- Get all of the jobs with an expired "score"...
|
|
|
109 |
local val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1], 'limit', 0, ARGV[2])
|
|
|
110 |
|
|
|
111 |
-- If we have values in the array, we will remove them from the first queue
|
|
|
112 |
-- and add them onto the destination queue in chunks of 100, which moves
|
|
|
113 |
-- all of the appropriate jobs onto the destination queue very safely.
|
|
|
114 |
if(next(val) ~= nil) then
|
|
|
115 |
redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)
|
|
|
116 |
|
|
|
117 |
for i = 1, #val, 100 do
|
|
|
118 |
redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))
|
|
|
119 |
-- Push a notification for every job that was migrated...
|
|
|
120 |
for j = i, math.min(i+99, #val) do
|
|
|
121 |
redis.call('rpush', KEYS[3], 1)
|
|
|
122 |
end
|
|
|
123 |
end
|
|
|
124 |
end
|
|
|
125 |
|
|
|
126 |
return val
|
|
|
127 |
LUA;
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
/**
|
|
|
131 |
* Get the Lua script for removing all jobs from the queue.
|
|
|
132 |
*
|
|
|
133 |
* KEYS[1] - The name of the primary queue
|
|
|
134 |
* KEYS[2] - The name of the "delayed" queue
|
|
|
135 |
* KEYS[3] - The name of the "reserved" queue
|
|
|
136 |
* KEYS[4] - The name of the "notify" queue
|
|
|
137 |
*
|
|
|
138 |
* @return string
|
|
|
139 |
*/
|
|
|
140 |
public static function clear()
|
|
|
141 |
{
|
|
|
142 |
return <<<'LUA'
|
|
|
143 |
local size = redis.call('llen', KEYS[1]) + redis.call('zcard', KEYS[2]) + redis.call('zcard', KEYS[3])
|
|
|
144 |
redis.call('del', KEYS[1], KEYS[2], KEYS[3], KEYS[4])
|
|
|
145 |
return size
|
|
|
146 |
LUA;
|
|
|
147 |
}
|
|
|
148 |
}
|