local newly_enqueued = 0
local newly_scheduled = 0
local idempotency_ttl = ARGV[1]
local emit_events = ARGV[2] == "1"
for i = 3, #ARGV, 7 do
local task_id = ARGV[i]
local task_data = ARGV[i + 1]
local attempts = ARGV[i + 2]
local max_attempts = ARGV[i + 3]
local metadata_json = ARGV[i + 4]
local schedule_time = tonumber(ARGV[i + 5])
local idempotency_key = ARGV[i + 6]
if task_id and task_data then
local allowed = true
if idempotency_key and #idempotency_key > 0 then
local idem_field = KEYS[6] .. ':' .. idempotency_key
local claimed = redis.call("setnx", idem_field, task_id)
if claimed == 0 then
allowed = false
else
if idempotency_ttl and #idempotency_ttl > 0 then
redis.call("expire", idem_field, idempotency_ttl)
end
end
end
if allowed then
local set = redis.call("hsetnx", KEYS[1], task_id, task_data)
if set == 1 then
local meta_key = KEYS[4] .. ':' .. task_id
local meta = {"attempts", tonumber(attempts), "max_attempts", tonumber(max_attempts), "status",
"Pending"}
table.insert(meta, "idempotency_key")
table.insert(meta, idempotency_key)
if metadata_json and #metadata_json > 0 then
local ok, decoded = pcall(cjson.decode, metadata_json)
if ok and type(decoded) == "table" then
for k, v in pairs(decoded) do
if type(v) == "table" then
v = cjson.encode(v)
end
table.insert(meta, k)
table.insert(meta, tostring(v))
end
end
end
redis.call("hmset", meta_key, unpack(meta))
if schedule_time and schedule_time > 0 then
redis.call("zadd", KEYS[5], schedule_time, task_id)
newly_scheduled = newly_scheduled + 1
else
redis.call("rpush", KEYS[2], task_id)
if emit_events then
redis.call("publish", "tasks:" .. KEYS[2] .. ':available', task_id)
end
newly_enqueued = newly_enqueued + 1
end
end
end
end
end
if newly_enqueued > 0 then
redis.call("del", KEYS[3])
redis.call("lpush", KEYS[3], 1)
end
return {newly_enqueued, newly_scheduled}