local max_receives = tonumber(ARGV[1])
local src_hash = KEYS[1] .. ":Q"
local dlq_hash = KEYS[4] .. ":Q"
local max_iter = 100
for _ = 1, max_iter do
local message = redis.call("ZRANGE", KEYS[1], "-inf", KEYS[2], "BYSCORE", "LIMIT", 0, 1)
if #message == 0 then
return { false, "", "", 0, 0 }
end
local id = message[1]
local body = redis.call("HGET", src_hash, id)
if not body then
redis.call("ZREM", KEYS[1], id)
else
redis.call("HINCRBY", src_hash, "totalrecv", 1)
local rc = redis.call("HINCRBY", src_hash, id .. ":rc", 1)
if rc > max_receives then
local fr = redis.call("HGET", src_hash, id .. ":fr") or KEYS[2]
local time = redis.call("TIME")
local dlq_score
if ARGV[2] == "1" then
dlq_score = tonumber(time[1]) * 1000000 + tonumber(time[2])
else
dlq_score = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)
end
redis.call("ZADD", KEYS[4], dlq_score, id)
redis.call("HSET", dlq_hash, id, body)
redis.call("HSET", dlq_hash, id .. ":rc", rc)
redis.call("HSET", dlq_hash, id .. ":fr", fr)
redis.call("HINCRBY", dlq_hash, "totalsent", 1)
redis.call("ZREM", KEYS[1], id)
redis.call("HDEL", src_hash, id, id .. ":rc", id .. ":fr")
else
local fr
if rc == 1 then
redis.call("HSET", src_hash, id .. ":fr", KEYS[2])
fr = KEYS[2]
else
fr = redis.call("HGET", src_hash, id .. ":fr")
end
redis.call("ZADD", KEYS[1], KEYS[3], id)
return { true, id, body, rc, fr }
end
end
end
return { false, "", "", 0, 0 }