require 'sidekiq' module Sidekiq module CircuitBreaker module API extend self def open_circuit(scope, ttl = 120) raise ArgumentError, 'scope must not be nil' if scope.nil? Sidekiq.redis do |conn| conn.setex(open_key(scope), ttl, 0) # reset failure count conn.del(failure_key(scope)) end true end def register_failure_for_scope(scope, ttl = 120) raise ArgumentError, 'scope must not be nil' if scope.nil? key = failure_key(scope) _, failure_count = Sidekiq.redis do |conn| conn.multi do conn.expire(key, ttl) conn.incr(key) end end failure_count end def register_success_for_scope(scope) raise ArgumentError, 'scope must not be nil' if scope.nil? Sidekiq.redis do |conn| conn.del(failure_key(scope), open_key(scope)) end end def time_to_open_the_circuit(scope) Sidekiq.redis do |conn| conn.ttl(open_key(scope)) end end def circuit_opened?(scope) Sidekiq.redis do |conn| conn.exists(open_key(scope)) end end def failure_count_for_scope(scope) Sidekiq.redis do |conn| conn.get(failure_key(scope)) end.to_i end private def redis_key(suffix) "sidekiq:circuit_breaker:#{suffix}" end def open_key(scope) redis_key("open:#{scope}") end def failure_key(scope) redis_key("failure:#{scope}") end end end end