class CircuitBreaker
def initialize(name, redis: Redis.current)
@name = name
@redis = redis
end
def allow?
@redis.get(open_key).nil?
end
def record_failure!(cooldown: 30)
@redis.set(open_key, '1', ex: cooldown)
end
private
def open_key
"cb:open:#{@name}"
end
end
breaker = CircuitBreaker.new('shipping_api')
raise 'Dependency temporarily unavailable' unless breaker.allow?
ShippingProvider.new.quote(...)
rescue Faraday::Error
breaker.record_failure!(cooldown: 60)
raise
When a dependency is failing, you don’t want to keep hammering it. A simple circuit breaker trips after N failures and short-circuits for a cooldown window. It protects your app and your vendor.