Module: Dynflow::Executors::Sidekiq::RedisLocking

Included in:
Core
Defined in:
lib/dynflow/executors/sidekiq/redis_locking.rb

Constant Summary collapse

REDIS_LOCK_KEY =
'dynflow_orchestrator_uuid'
REDIS_LOCK_TTL =
60
REDIS_LOCK_POLL_INTERVAL =
15
ACQUIRE_OK =
0
ACQUIRE_MISSING =
1
ACQUIRE_TAKEN =
2
RELEASE_SCRIPT =
<<~LUA
  if redis.call("get", KEYS[1]) == ARGV[1] then
    redis.call("del", KEYS[1])
  end
  return #{ACQUIRE_OK}
LUA
REACQUIRE_SCRIPT =
<<~LUA
  if redis.call("exists", KEYS[1]) == 1 then
    local owner = redis.call("get", KEYS[1])
    if owner == ARGV[1] then
      redis.call("set", KEYS[1], ARGV[1], "XX", "EX", #{REDIS_LOCK_TTL})
      return #{ACQUIRE_OK}
    else
      return #{ACQUIRE_TAKEN}
    end
  else
    redis.call("set", KEYS[1], ARGV[1], "NX", "EX", #{REDIS_LOCK_TTL})
    return #{ACQUIRE_MISSING}
  end
LUA

Instance Method Summary collapse

Instance Method Details

#reacquire_orchestrator_lockObject



57
58
59
60
61
62
63
64
65
66
# File 'lib/dynflow/executors/sidekiq/redis_locking.rb', line 57

def reacquire_orchestrator_lock
  case ::Sidekiq.redis { |conn| conn.eval REACQUIRE_SCRIPT, [REDIS_LOCK_KEY], [@world.id] }
  when ACQUIRE_MISSING
    @logger.error('The orchestrator lock was lost, reacquired')
  when ACQUIRE_TAKEN
    owner = ::Sidekiq.redis { |conn| conn.get REDIS_LOCK_KEY }
    @logger.fatal("The orchestrator lock was stolen by #{owner}, aborting.")
    Process.kill('INT', Process.pid)
  end
end

#release_orchestrator_lockObject



37
38
39
# File 'lib/dynflow/executors/sidekiq/redis_locking.rb', line 37

def release_orchestrator_lock
  ::Sidekiq.redis { |conn| conn.eval RELEASE_SCRIPT, [REDIS_LOCK_KEY], [@world.id] }
end

#wait_for_orchestrator_lockObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/dynflow/executors/sidekiq/redis_locking.rb', line 41

def wait_for_orchestrator_lock
  mode = nil
  loop do
    active = ::Sidekiq.redis do |conn|
      conn.set(REDIS_LOCK_KEY, @world.id, :ex => REDIS_LOCK_TTL, :nx => true)
    end
    break if active
    if mode.nil?
      mode = :passive
      @logger.info('Orchestrator lock already taken, entering passive mode.')
    end
    sleep REDIS_LOCK_POLL_INTERVAL
  end
  @logger.info('Acquired orchestrator lock, entering active mode.')
end