Module: RubyLLM::Resilience
- Defined in:
- lib/ruby_llm/resilience.rb,
lib/ruby_llm/resilience/chain.rb,
lib/ruby_llm/resilience/engine.rb,
lib/ruby_llm/resilience/errors.rb,
lib/ruby_llm/resilience/breaker.rb,
lib/ruby_llm/resilience/version.rb,
lib/ruby_llm/resilience/tier_namer.rb,
lib/ruby_llm/resilience/memory_store.rb,
lib/ruby_llm/resilience/configuration.rb,
lib/generators/resilience/install_generator.rb,
app/controllers/ruby_llm/resilience/breakers_controller.rb
Overview
Circuit breakers and fallback chains for LLM apps.
RubyLLM::Resilience.configure do |c|
c.cache_store = ActiveSupport::Cache::RedisCacheStore.new(...)
c.fallback_models = { "claude-haiku-4-5" => "claude-sonnet-4-6" }
c.on_error = ->(error, ctx) { Rails.error.report(error, context: ctx) }
c.on_status = ->(service, state) { Appsignal.set_gauge("circuit_breaker.state", state == :open ? 1 : 0, service:) }
end
RubyLLM::Resilience.run("api:openai:embeddings") { RubyLLM.embed(text) }
Defined Under Namespace
Modules: Chain, ErrorResolution, TierNamer Classes: Breaker, BreakerTripped, BreakersController, Configuration, Engine, InstallGenerator, MemoryStore
Constant Summary collapse
- VERSION =
"0.6.0"
Class Method Summary collapse
- .config ⇒ Object
-
.configure {|@config| ... } ⇒ Object
Configure once at boot; the configuration freezes afterwards so fiber/thread safety comes from immutability.
-
.fallback_routes ⇒ Object
Fallback routing grouped by breaker service, for dashboards: { "api:anthropic:haiku" => ["claude-haiku-4-5 → claude-sonnet-4-6"], ... } A service can carry several routes when multiple models map into the same tier breaker.
- .reset_configuration! ⇒ Object
- .run(service, &block) ⇒ Object
- .run_with_fallback(*steps) ⇒ Object
- .run_with_model_fallback(primary_model, fallback: :map, &block) ⇒ Object
-
.service_for(model_name) ⇒ Object
Convenience: the breaker name the configured service_namer would assign to a model.
- .trippable?(error) ⇒ Boolean
Class Method Details
.config ⇒ Object
28 29 30 |
# File 'lib/ruby_llm/resilience.rb', line 28 def config @config ||= Configuration.new end |
.configure {|@config| ... } ⇒ Object
Configure once at boot; the configuration freezes afterwards so fiber/thread safety comes from immutability. Use reset_configuration! in tests.
35 36 37 38 39 40 |
# File 'lib/ruby_llm/resilience.rb', line 35 def configure @config ||= Configuration.new yield @config @config.freeze @config end |
.fallback_routes ⇒ Object
Fallback routing grouped by breaker service, for dashboards:
{ "api:anthropic:haiku" => ["claude-haiku-4-5 → claude-sonnet-4-6"], ... }
A service can carry several routes when multiple models map into the same tier breaker.
74 75 76 77 78 79 80 |
# File 'lib/ruby_llm/resilience.rb', line 74 def fallback_routes config.fallback_models.keys.each_with_object(Hash.new { |h, k| h[k] = [] }) do |model, routes| service = service_for(model) chain = [ model, *config.fallbacks_for(model) ] routes[service] << chain.join(" → ") end end |
.reset_configuration! ⇒ Object
42 43 44 45 46 |
# File 'lib/ruby_llm/resilience.rb', line 42 def reset_configuration! @config = Configuration.new Breaker.reset_registry! @config end |
.run(service, &block) ⇒ Object
48 49 50 |
# File 'lib/ruby_llm/resilience.rb', line 48 def run(service, &block) Chain.run(service, &block) end |
.run_with_fallback(*steps) ⇒ Object
56 57 58 |
# File 'lib/ruby_llm/resilience.rb', line 56 def run_with_fallback(*steps) Chain.run_with_fallback(*steps) end |
.run_with_model_fallback(primary_model, fallback: :map, &block) ⇒ Object
52 53 54 |
# File 'lib/ruby_llm/resilience.rb', line 52 def run_with_model_fallback(primary_model, fallback: :map, &block) Chain.run_with_model_fallback(primary_model, fallback: fallback, &block) end |
.service_for(model_name) ⇒ Object
Convenience: the breaker name the configured service_namer would assign to a model.
66 67 68 |
# File 'lib/ruby_llm/resilience.rb', line 66 def service_for(model_name) config.service_namer.call(model_name) end |
.trippable?(error) ⇒ Boolean
60 61 62 |
# File 'lib/ruby_llm/resilience.rb', line 60 def trippable?(error) config.resolved_trippable_errors.any? { |klass| error.is_a?(klass) } end |