8 comments

[ 3.4 ms ] story [ 24.8 ms ] thread
Hey HN! I extracted BreakerMachines from my apps after seeing people dealing with cascading failures in production Rails apps.

Key features that set it apart:

- True async/fiber support (works with Falcon, async gems)

- Built-in fallback mechanism with chaining

- Thread-safe without dangerous Timeout.timeout

- Memory-efficient with WeakRef tracking

- Rich introspection and monitoring hooks

- Clean DSL that works with inheritance

With everyone adding AI/LLM APIs to their apps, circuit breakers are more critical than ever.

These APIs can be slow, flaky, or have outages - without protection, your app goes down with them.

The README shows patterns for graceful degradation when a service is down.

I explicitly avoided shipping Redis/DB adapters to keep it focused, the README shows how to implement your own in ~20 lines.

Would love feedback on the API design and any edge cases I might have missed!

I'm still going to add the parallel feature, i removed it because i need to test it in CI.

> Would love feedback on the API design

I'd suggest to drop the DSL, at the end of the day, a good old class with a constructor stored in a constant is much more more transparent:

    class PaymentService
      STRIPE_CIRCUIT = BreakerMachines::Circuit.new(
        threshold: { failures: 3, within: 1.minute },
        reset_after: 30.seconds,
        fallback: ->{ { error: "Payment queued for later" } }
      )

      def charge(amount)
        STRIPE_CIRCUIT.wrap do
          Stripe::Charge.create(amount: amount)
        end
      end
    end

Just my 2 cents though.
I’m usually weary of long readmes with too much styling as that indicates to me a high likelihood that they were written by ai and the author might not have even read all of it. The use of generic ai images also gives a bad impression - for example, there’s an image captioned “The green lines? Those are your CPU cycles escaping.” without anything green pictured.

I’m not saying your gem is bad. It’s nice to se an attempt at a circuit breaker that is based on the state machines gem, I will certainly look into the actual code if I have a need for it in the future.

Just wanted to give you this bit of feedback about maybe cutting down on length and loosing the ai images in the readme as I think it might be a turnoff for others as well.

Reading this I expected the README to be unreadable, filled with images and emojis, but found them to be very detailed with lots of code examples (Which I often miss in Gems) and explanations which was obviously a lot of work to do. Thanks for that!

PS: Speaking of "bit of feedback" for the parent commenter, it's losing not loosing.

I'm sure I saw this gem posted a few days ago (maybe not on HN?) and at the time all the docs were in one mahoosive README.

I think it's a massive improvement that it's been broken down into chapters in a docs folder. I can take or leave the writing style but do miss the old whimsy of _why and his poignant guide to ruby. The examples are great and quite thorough.

(comment deleted)
I've generally found token bucket retries a lot better than circuit breakers which by nature are very bi-modal, sending no requests then floods of requests in higher scale systems. This can cause issues with memory and garbage collection when it's flapping on the order of milliseconds to seconds, and cause isues with load balancers and autoscaling when operating on the order of minutes. Token Buckets tend to dial the pressue up and down more smoothly. It's like the difference between an old fashioned thermostat and a PID loop for controlling a temperature setpoint.
> Welcome to April 2005—when Git was born, branches were just master, and nobody cared about your pronouns.

JFC, whatever happened to "Matz is nice, so we are nice"?