Andy Rusterholz

Projects

Two Ruby gems I write and maintain. Both are on RubyGems under the MIT license. Neither has a hosted demo yet, though each repository carries a working demo application you can run locally.

busybee

v0.3.0·MIT·Ruby ≥ 3.2

Outgrowing a monolith usually means splitting it into services, and that trade is rarely as clean as the diagram. Your business processes don't split as neatly. An order still has to be placed, paid for, routed, and fulfilled, but now those steps live in five codebases that only talk by publishing events at each other. No single thing describes the process any more. Answering "where did this order get stuck?" means reading five services' logs. Every engineer needs to think about duplicate and out-of-order messages. And the process at the core of your business stops being subject to change review.

The mature answer comes from the enterprise world: it's called workflow orchestration, and it inverts the arrangement. Instead of being an emergent property of which services happen to subscribe to what, the process becomes an explicit artifact, executed by an engine that owns the state, the retries, the timers, and what to undo when a step fails. Each service goes back to doing its own work, when it's asked. You get one document that says what the process is, and a live view of where every order currently sits inside it.

Busybee brings workflow orchestration to Ruby, which is hungry for durable execution right now (Rails 8.1's job continuations, Temporal's SDK, ductwork). So far, that has mostly meant writing your process as code. Busybee comes from the other tradition, where the diagram is the program: a BPMN document, an ISO standard since 2013, made to be readable by people who don't write Ruby. It runs on Camunda, the orchestration platform behind Goldman Sachs, Atlassian, and Airbus, but you don't need a whole platform team to run it -- just this gem and a Camunda Cloud account.

Job handlers are plain Ruby classes with a small DSL (near enough to a Sidekiq worker to be legible on sight). A CLI runs those and owns the rest: the job lifecycle, retry backoff, graceful shutdown. With that comes an idiomatic Zeebe client and RSpec integration that verifies your workflow's real behavior against a live engine. And that last piece matters more than it sounds: orchestration gets adopted or avoided depending on whether a team can test it, so testability was a first-class design goal. I spent five years architecting and operating one of these platforms for a marketplace moving half a million events a day, working out everything from gRPC stubs to thread pools. But those in-house platforms stay in-house, and Ruby's canonical Zeebe client is archived. Busybee exists so the next team doesn't have to start from nothing.

weft

v0.2.0·MIT·Ruby ≥ 3.2

Using someone else's software, you've likely had this thought: there should be a button right here, and when I click it, it should do this. The right affordance can be obvious enough that its absence itches.

But building it almost never feels as pure as that first moment. That one sentence becomes a new route, a controller action, a template (or a React component), and some client-side glue, spread across files in two languages, and usually a meeting to settle which piece goes where. Almost all of it comes down to convention, and Rails settled the argument about convention a long time ago.

Weft keeps that sentence intact, all the way to the code. The button is button "Publish", action: :publish. What it does is performs(:publish) { |p| Draft.find(p.draft_id).publish! }. Both sit in the same component class, and from those two declarations the framework derives the route, the request handling, and the htmx attributes that wire the browser up. No routes file, no controllers, no JavaScript of your own. It runs standalone on Sinatra, or as Rack middleware inside an app you already have.

The idea of declaring UI behavior server-side isn't new. ActiveAdmin had it before me, and Weft is built on Arbre, the templating engine they wrote to keep the DOM tree in Ruby. But ActiveAdmin is resource-oriented by design; it takes the interface decisions out of your hands on purpose. I wanted them in mine, and getting there meant hand-stitching every piece (collapsible panels, custom action buttons) across custom components and endpoints scattered through its files. Weft is how I wanted to be writing instead: a different approach to thinking about an app than MVC asks for. It's early, but v0.2 is complete enough to build on, with a tutorial and twenty-one worked examples. And weft-rails, which will make that Rack middleware path comfortable rather than merely possible, is next.