class Resque::Scheduler::Lock::Resilient

def acquire!

def acquire!
  evalsha(:acquire, [key], [value]).to_i == 1
end

def acquire_sha(refresh = false)

def acquire_sha(refresh = false)
  @acquire_sha = nil if refresh
  @acquire_sha ||=
    Resque.data_store.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
      if redis.call('SETNX', KEYS[1], ARGV[1]) == 1
      then
        redis.call('EXPIRE', KEYS[1], #{timeout})
        return 1
      else
        return 0
      end
    EOF
end

def evalsha(script, keys, argv, refresh: false)

def evalsha(script, keys, argv, refresh: false)
  sha_method_name = "#{script}_sha"
  Resque.redis.evalsha(
    send(sha_method_name, refresh),
    keys: keys,
    argv: argv
  )
rescue Redis::CommandError => e
  if e.message =~ /NOSCRIPT/
    refresh = true
    retry
  end
  raise
end

def locked?

def locked?
  evalsha(:locked, [key], [value]).to_i == 1
end

def locked_sha(refresh = false)

def locked_sha(refresh = false)
  @locked_sha = nil if refresh
  @locked_sha ||=
    Resque.data_store.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
      if redis.call('GET', KEYS[1]) == ARGV[1]
      then
        redis.call('EXPIRE', KEYS[1], #{timeout})
        if redis.call('GET', KEYS[1]) == ARGV[1]
        then
          return 1
        end
      end
      return 0
    EOF
end

def timeout=(seconds)

def timeout=(seconds)
  if locked?
    @timeout = seconds
    @locked_sha = nil
    @acquire_sha = nil
  end
  @timeout
end