Skip to content

Instantly share code, notes, and snippets.

@OleksandrKucherenko
Created October 5, 2018 12:19
Show Gist options
  • Save OleksandrKucherenko/77a65ae9f641308f156fe3b85098fc94 to your computer and use it in GitHub Desktop.
Save OleksandrKucherenko/77a65ae9f641308f156fe3b85098fc94 to your computer and use it in GitHub Desktop.
Redis LUA script. Reserve instance from queue/list with TTL.
local list = KEYS[1]
local user = KEYS[2]
local instance = redis.call('RPOPLPUSH', list, list)
if nil == instance then return nil end
local first = instance
while true do
local id = string.sub(tostring(instance), string.len('instance.') + 1)
local reserved = 'reserved.' .. id
local confirmed = redis.call('SET', reserved, user, 'EX', 2400, 'NX')
if type(confirmed) == "table" then
if confirmed['ok'] == 'OK' then return instance end
end
instance = redis.call('RPOPLPUSH', list, list)
if first == instance then break end
end
return nil
@OleksandrKucherenko
Copy link
Author

Usage:

const Redis = require('ioredis')
const REDIS_URL = '{your instance name}.amazonaws.com'
const QUEUE_AVAILABLE = 'genymotion-queue'
const REDIS_SET_TIMEOUT_SECONDS = 40 * 60

    const redis = new Redis(6379, REDIS_URL)
        redis.defineCommand('reserveWithTtl', {
          numberOfKeys: 2,
          lua: `
local list = KEYS[1]
local user = KEYS[2]
local instance = redis.call('RPOPLPUSH', list, list)
if nil == instance then return instance end
local first = instance

while true do 
  local id = string.sub(tostring(instance), string.len('instance.') + 1)
  local reserved = 'reserved.' .. id
  local confirmed = redis.call('SET', reserved, user, 'EX', ${REDIS_SET_TIMEOUT_SECONDS}, 'NX')
  if type(confirmed) == "table" then 
    if confirmed['ok'] == 'OK' then return instance end
  end
  
  instance = redis.call('RPOPLPUSH', list, list)
  if first == instance then break end
end

return nil
`,
        })
        instance = await redis.reserveWithTtl(QUEUE_AVAILABLE, user)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment