Class: Stoplight::Infrastructure::Memory::Storage::State

Inherits:
Object
  • Object
show all
Defined in:
lib/stoplight/infrastructure/memory/storage/state.rb

Overview

Thread-safe in-memory state storage for a single light.

Manages light state transitions and ensures notification deduplication through atomic transition detection. Each transition method returns whether the calling thread was first to trigger that transition, enabling exactly-once notification semantics.

Examples:

Basic usage

state = State.new(clock: SystemClock.new, cool_off_time: 60)

# Multiple threads may call this concurrently
if state.transition_to_color(Color::RED)
  # Only one thread reaches here - send notification
  notifier.notify(circuit_name, :opened)
end

Inspecting current state

snapshot = state.state_snapshot
snapshot.locked_state        # => "unlocked"
snapshot.breached_at         # => 2025-01-15 10:30:00 UTC
snapshot.recovery_scheduled_after  # => 2025-01-15 10:31:00 UTC

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(clock:, cool_off_time:) ⇒ State



32
33
34
35
36
37
# File 'lib/stoplight/infrastructure/memory/storage/state.rb', line 32

def initialize(clock:, cool_off_time:)
  @locked_state = Stoplight::State::UNLOCKED
  @mutex = Thread::Mutex.new
  @clock = clock
  @cool_off_time = cool_off_time
end

Instance Method Details

#clearObject



74
75
76
77
78
79
80
81
82
# File 'lib/stoplight/infrastructure/memory/storage/state.rb', line 74

def clear
  mutex.synchronize do
    self.locked_state = Stoplight::State::UNLOCKED
    self.recovered_at = nil
    self.recovery_scheduled_after = nil
    self.breached_at = nil
    self.recovery_started_at = nil
  end
end

#set_state(state) ⇒ Object



39
40
41
42
43
# File 'lib/stoplight/infrastructure/memory/storage/state.rb', line 39

def set_state(state)
  mutex.synchronize do
    self.locked_state = state
  end
end

#state_snapshotObject



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/stoplight/infrastructure/memory/storage/state.rb', line 45

def state_snapshot
  mutex.synchronize do
    Domain::StateSnapshot.new(
      time: clock.current_time,
      locked_state:,
      recovery_scheduled_after:,
      recovery_started_at:,
      breached_at:
    )
  end
end

#transition_to_color(color) ⇒ Object

Combined method that performs the state transition based on color



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/stoplight/infrastructure/memory/storage/state.rb', line 61

def transition_to_color(color)
  case color
  when Color::GREEN
    transition_to_green
  when Color::YELLOW
    transition_to_yellow
  when Color::RED
    transition_to_red
  else
    raise ArgumentError, "Invalid color: #{color}"
  end
end