Ruby Reactor Now Has Middlewares and OpenTelemetry — Here's Why That Matters
You've built a checkout reactor that reserves inventory, charges a card, generates a shipping label, and sends a confirmation email. It runs through Sidekiq. When something fails, compensation logic rolls it back. It works. Then your team asks: "How many checkouts failed this week? Which step? How long does the charge step take at p99? Can we see a trace through the entire system?" Before v0.5.0, you'd need to add logging calls to every step, build a custom Sidekiq middleware, and figure out how to correlate traces across async job boundaries. Now it's one line of config. Enter Middlewares Ruby Reactor 0.5.0 introduces a middleware pipeline — the same pattern that powers Rack, but designed for saga execution. A middleware is a plain Ruby object that hooks into the reactor lifecycle: class TimingMiddleware < RubyReactor :: Middleware def initialize ( ** options ) super @started = {} end def on_start_step ( step_name , _arguments , _context ) @started [ step_name ] = Process . clock_gettime ( Process :: CLOCK_MONOTONIC ) end def on_complete_step ( step_name , _result , _context ) started = @started . delete ( step_name ) return unless started elapsed = Process . clock_gettime ( Process :: CLOCK_MONOTONIC ) - started logger . info ( "step #{ step_name } took #{ elapsed . round ( 4 ) } s" ) end end This middleware times every step. Register it globally: RubyReactor . configure do | config | config . middlewares = [ TimingMiddleware ] end Now every reactor — every checkout, every refund, every data import — gets step-level timing, for free. The full lifecycle (20+ events) Middlewares can observe the complete execution lifecycle: Phase Events Reactor on_start_reactor , on_complete_reactor , on_failed_reactor Step on_start_step , on_complete_step , on_failed_step , on_retry_attempt Compensation on_start_compensation , on_complete_compensation , on_failed_compensation Undo on_start_undo , on_complete_undo , on_failed_undo Coordination on_lock_acquired , on_lock_failed , on_