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 =
"if redis.call(\"get\", KEYS[1]) == ARGV[1] then\n  redis.call(\"del\", KEYS[1])\nend\nreturn \#{ACQUIRE_OK}\n"
REACQUIRE_SCRIPT =
"if redis.call(\"exists\", KEYS[1]) == 1 then\n  local owner = redis.call(\"get\", KEYS[1])\n  if owner == ARGV[1] then\n    redis.call(\"set\", KEYS[1], ARGV[1], \"XX\", \"EX\", \#{REDIS_LOCK_TTL})\n    return \#{ACQUIRE_OK}\n  else\n    return \#{ACQUIRE_TAKEN}\n  end\nelse\n  redis.call(\"set\", KEYS[1], ARGV[1], \"NX\", \"EX\", \#{REDIS_LOCK_TTL})\n  return \#{ACQUIRE_MISSING}\nend\n"

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