local poolkey = KEYS[1] local qkey = KEYS[2] local activekey = KEYS[3] local checkin_item = ARGV[1] if redis.call('EXISTS', poolkey) == 0 then return { -1, {} } -- pool doesn't exist end if checkin_item ~= "" then redis.call("HDEL", activekey, checkin_item) redis.call("HINCRBY", poolkey, "complete_count", 1) end local pool_type = redis.call('HGET', poolkey, "order") local allotment = tonumber(redis.call("HGET", poolkey, "concurrency")) local active = redis.call("HLEN", activekey) + (redis.call("HGET", poolkey, "_active_count") or 0) local pop_count = allotment - active local popped_items = {} if pop_count > 0 then if pool_type == "fifo" then popped_items = redis.call("LPOP", qkey, pop_count) or {} elseif pool_type == "lifo" then popped_items = redis.call("RPOP", qkey, pop_count) or {} elseif pool_type == "random" then popped_items = redis.call("SPOP", qkey, pop_count) or {} elseif pool_type == "priority" then local temp_items = redis.call("ZPOPMAX", qkey, pop_count) or {} for i,v in ipairs(temp_items) do if i % 2 == 1 then table.insert(popped_items, v) end end end end -- Reserve slots for these jobs while we return to Ruby and deserialize them -- This could also be inlined by just storing a key in the queue and storing parameters -- in a Hash, but this seems more efficient. redis.call('HINCRBY', poolkey, "_active_count", #popped_items) return { active, popped_items }