Ruby gem implementing the circuit breaker pattern. This is library code, not an application.
Public API lives in lib/stoplight.rb.
bundle install # install deps
bundle exec standardrb --fix # lint with autofix
bundle exec steep check # RBS type check
bundle exec rspec # all specs
bundle exec rspec spec/unit/stoplight/domain/light_spec.rb:42 # run one file/example
STOPLIGHT_DATA_STORE=Memory bundle exec cucumber # features with Memory store
STOPLIGHT_DATA_STORE=Redis bundle exec cucumber # features with Redis storeClean Architecture, four layers, dependencies point inward only. A custom cop
(Stoplight/ArchitectureBoundaries, severity error) enforces this - a violation
fails lint:
Layer (lib/stoplight/…) |
May depend on |
|---|---|
domain/ |
nothing |
infrastructure/ |
domain |
wiring/ |
domain, infrastructure |
admin/ |
domain, infrastructure, wiring |
- Domain is pure: no I/O, no Redis, no gems. It defines interfaces as RBS type
signatures only (
sig/_private/stoplight/domain/ports/), never Ruby base classes. - Infrastructure implements those interfaces by duck typing (no inheritance).
- Domain must never reference the composition root (
Stoplight.light/Stoplight.register/.configure/.light/Stoplight()) or the root aliasesStoplight::DataStore/Stoplight::Notifier. UseDomain::Lightand domain interfaces directly. - The same boundary rule applies to specs under
spec/unit/<layer>/.
Full detail: docs/architecture.md.
# frozen_string_literal: trueat the top of every Ruby file.- Let zeitwerk autoload - no manual
requireinsidelib/. File path = constant path. - Internal-but-public plumbing uses the
__stoplight__prefix. - Public surface is only:
Stoplight(),Stoplight.register,Stoplight.light,Stoplight.configure,Stoplight.telemetry,Light#run - Public API methods require a doc comment with at least one usage example -
see
lib/stoplight.rbfor the pattern. Document behavior, not types - types belong in RBS (docs/types_and_rbs.md). - Domain collaborator ports are RBS interfaces with no runtime constant - test
doubles use the
Null*classes inspec/support/adapters/, e.g.instance_double(NullStateStore). Seedocs/testing.md. - Any change in
lib/needs matching RBS insig/(seedocs/types_and_rbs.md).
domain/- light state machine, colors (green/yellow/red), failure model, run strategies,traffic_control(consecutive_errors,error_rate-> trip to red),traffic_recovery(consecutive_successes), recovery probes + recovery locks.infrastructure/- memory + redis stores, notifiers,fail_safewrappers. Redis writes go through co-located Lua scripts for atomicity. Storage is a decomposedStorage/StorageSetmodel - target the focused stores for new work.wiring/- dependency injection / composition root, config DSLs, defaults.admin/- optional Sinatra dashboard (excluded from Steep type checking).sig/- RBS;sig/_private/holds internal interfaces.bench/- benchmarks.spec/dummy/- a Rails app used to test the install generator.