-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue.lua
More file actions
214 lines (194 loc) · 6.83 KB
/
queue.lua
File metadata and controls
214 lines (194 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#!lua name=queue
--- Библиотека для работы с очередью
---
-- Перемешивает элементы в списке
--
-- @param list список
-- @return перемешанный список
--
local function shuffle_list(list)
for i = #list, 2, -1 do
local j = math.random(i)
list[i], list[j] = list[j], list[i]
end
end
---
-- Добавляет элемент в конец очереди
--
-- @param keys[1] ключ очереди
-- @param argv[1] значение, которое необходимо добавить
-- @return количество элементов в очереди
--
local function push(keys, argv)
return redis.call('RPUSH', keys[1], argv[1])
end
---
-- Удаляет и возвращает первый элемент очереди
--
-- @param keys[1] ключ очереди
-- @return первый элемент очереди
--
local function pop(keys)
return redis.call('LPOP', keys[1])
end
---
-- Возвращает все элементы очереди
--
-- @param keys[1] ключ очереди
-- @return все элементы очереди
--
local function get(keys)
return redis.call('LRANGE', keys[1], 0, -1)
end
---
-- Удаляет все элементы очереди
--
-- @param keys[1] ключ очереди
-- @return количество удаленных элементов
--
local function clear(keys)
return redis.call('DEL', keys[1])
end
---
-- Возвращает количество элементов в очереди
--
-- @param keys[1] ключ очереди
-- @return количество элементов в очереди
--
local function length(keys)
-- Если такого list нет, то вернуть ошибку
if redis.call('EXISTS', keys[1]) == 0 then
return redis.error_reply('ERR no such key')
end
return redis.call('LLEN', keys[1])
end
---
-- Перемешивает элементы в очереди
--
-- @param keys[1] ключ очереди
--
local function shuffle(keys)
local list = redis.call('LRANGE', keys[1], 0, -1)
shuffle_list(list)
redis.call('DEL', keys[1])
for _, value in ipairs(list) do
redis.call('RPUSH', keys[1], value)
end
end
---
-- Перемещение элемента по индексам
--
-- @param keys[1] ключ очереди
-- @param argv[1] индекс перемещаемого элемента
-- @param argv[2] индекс, перед которым необходимо вставить элемент
--
local function move(keys, argv)
local value = redis.call('LINDEX', keys[1], argv[1])
if value then
redis.call('LREM', keys[1], 0, value)
redis.call('LINSERT', keys[1], 'BEFORE', redis.call('LINDEX', keys[1], argv[2]), value)
end
end
---
-- Удаление элемента по индексу
--
-- @param keys[1] ключ очереди
-- @param argv[1] индекс удаляемого элемента
--
local function remove(keys, argv)
local value = redis.call('LINDEX', keys[1], argv[1])
if value then
redis.call('LREM', keys[1], 0, value)
end
end
---
-- Вставка элемента по индексу
--
-- @param keys[1] ключ очереди
-- @param argv[1] индекс, перед которым необходимо вставить элемент
-- @param argv[2] значение, которое необходимо вставить
--
local function insert(keys, argv)
redis.call('LINSERT', keys[1], 'BEFORE', redis.call('LINDEX', keys[1], argv[1]), argv[2])
end
---
-- Возвращает элемент по индексу
--
-- @param keys[1] ключ очереди
-- @param argv[1] индекс элемента
-- @return элемент очереди
--
local function index(keys, argv)
return redis.call('LINDEX', keys[1], argv[1])
end
---
-- Скип n первых элементов
--
-- @param keys[1] ключ очереди
-- @param argv[1] количество элементов, которые необходимо пропустить
--
local function skip(keys, argv)
local n = argv[1] or 1
for i = 1, n do
redis.call('LPOP', keys[1])
end
end
---
-- Добавление элемента в начало очереди
--
-- @param keys[1] ключ очереди
-- @param argv[1] значение, которое необходимо добавить
-- @return количество элементов в очереди
--
local function unshift(keys, argv)
return redis.call('LPUSH', keys[1], argv[1])
end
---
-- Добавить новый элемент в очередь, учитывая максимальную длину
--
-- @param keys[1] ключ очереди
-- @param argv[1] значение, которое необходимо добавить
-- @param argv[2] максимальная длина очереди
-- @return количество элементов в очереди
--
local function push_with_max_length(keys, argv)
-- Проверяем, что очередь меньше максимальной длины
local length = redis.call('LLEN', keys[1])
if length < argv[2] then
return redis.call('RPUSH', keys[1], argv[1])
end
-- Вернуть ошибку, если очередь полна
return redis.error_reply('ERR Queue is full')
end
local function push_with_check(keys, argv)
local queue_id = keys[1]:match('queue:(%d+)')
-- Вытягиваем json из session_data:queue_id
local max_length = cjson.decode(redis.call('GET', 'session_data:' .. queue_id))['max_length']
-- Проверяем, что очередь меньше максимальной длины
local length = redis.call('LLEN', keys[1])
if length < max_length then
return redis.call('RPUSH', keys[1], argv[1])
end
-- Вернуть ошибку, если очередь полна
return redis.error_reply('ERR Queue is full')
end
redis.register_function('push_with_max_length', push_with_max_length)
redis.register_function('push_with_check', push_with_check)
redis.register_function('push', push)
redis.register_function('pop', pop)
redis.register_function('get', get)
redis.register_function('clear', clear)
redis.register_function('length', length)
redis.register_function('shuffle', shuffle)
redis.register_function('move', move)
redis.register_function('remove', remove)
redis.register_function('insert', insert)
redis.register_function('index', index)
redis.register_function('skip', skip)
redis.register_function('unshift', unshift)
redis.register_function(
'lib_version',
function()
return 'queue.lua 0.0.2'
end
)