Skip to content

Wire LockChanged event #751

Description

@bolshakov

Stoplight has an internal "telemetry bus": typed event objects get emitted at key moments (a
run finishing, a color change, a lock toggling), and any code that subscribed to that event type
is called with it. Emitter#emit already no-ops cheaply when nobody's subscribed, so there's no
need to check that yourself before calling it.

The original design is PR #721 -- read its
"Motivation" and "What this opens up" sections for the why. All the event types it proposed
already exist as typed value objects (Data.define) under lib/stoplight/domain/telemetry/,
with public RBS signatures under sig/stoplight/telemetry/ -- the shape of every payload is
already decided, so this issue is not about designing anything new. Only RunCompleted is
actually wired up and firing today (PR #742, PR #741). This issue wires up one more:
LockChanged.

lib/stoplight/domain/telemetry/emitter.rb and lib/stoplight/domain/telemetry/run_recorder.rb
show one way this has been done, for RunCompleted -- worth reading for orientation, not a
template to force-fit. run_recorder.rb exists because RunCompleted needed duration measured
and shared across three call sites; that shape may or may not fit this event. Any change under
lib/ needs a matching change under sig/.

What you're wiring up

LockChanged (lib/stoplight/domain/telemetry/lock_changed.rb,
sig/stoplight/telemetry/lock_changed.rbs) fires whenever a human (or a script) manually locks
or unlocks a light -- overriding whatever color the automatic circuit-breaker logic would pick.

Read the sig's own doc comment carefully: this event fires even when the effective color
doesn't change
(e.g. locking an already-red light to red again still emits). The point is the
lock action itself being recorded, not a color transition -- don't add a "did the color
actually change" guard, that would be wrong here specifically (unlike the other events in this
set).

Where to make the change

Two separate call paths both need this, since Stoplight has two ways to lock/unlock a light: Domain::Light#lock / #unlock

Payload fields

  • from_color: / to_color: -- read before/after set_state, or derive from the requested lock
    state (State::LOCKED_RED implies Color::RED, etc.) if reading "before" isn't cheap.
  • from_state: / to_state: -- the light's locked state before and after the call (State::LOCKED_RED,
    State::LOCKED_GREEN, State::UNLOCKED).
  • source: -- remove this field from the event. We decided not to add this information.

References

Metadata

Metadata

Assignees

Labels

good first issueFor newcomers to learn the codebase. Human contributions only, AI-assisted PRs not accepted

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions