Class: CircuitBreaker::Workflow

Inherits:
Object
  • Object
show all
Defined in:
lib/circuit_breaker.rb

Overview

Main workflow class that manages the Petri net Can be created from a configuration or built programmatically

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(states: [], transitions: {}, before_flows: [], rules: []) ⇒ Workflow

Returns a new instance of Workflow.



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/circuit_breaker.rb', line 165

def initialize(states: [], transitions: {}, before_flows: [], rules: [])
  @places = {}
  @transitions = {}
  @tokens = Set.new
  @rules = rules
  @before_flows = before_flows

  self.states = states
  transitions.each do |transition, data|
    add_transition(transition, data[:from], data[:to])
    @transitions[transition].set_guard do |token|
      data[:rules]&.each { |rule| return false unless @rules.evaluate(rule, token) }
      true
    end
  end
end

Instance Attribute Details

#placesObject (readonly)

Returns the value of attribute places.



163
164
165
# File 'lib/circuit_breaker.rb', line 163

def places
  @places
end

#rulesObject (readonly)

Returns the value of attribute rules.



163
164
165
# File 'lib/circuit_breaker.rb', line 163

def rules
  @rules
end

#tokensObject (readonly)

Returns the value of attribute tokens.



163
164
165
# File 'lib/circuit_breaker.rb', line 163

def tokens
  @tokens
end

#transitionsObject (readonly)

Returns the value of attribute transitions.



163
164
165
# File 'lib/circuit_breaker.rb', line 163

def transitions
  @transitions
end

Instance Method Details

#add_token(token) ⇒ Object



188
189
190
191
192
# File 'lib/circuit_breaker.rb', line 188

def add_token(token)
  token.state = @places.keys.first if token.state.nil?
  @tokens.add(token)
  @places[token.state].add_token(token)
end

#fire_transition(transition_name, token) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/circuit_breaker.rb', line 194

def fire_transition(transition_name, token)
  transition = @transitions[transition_name]
  raise "Invalid transition: #{transition_name}" unless transition
  raise "Invalid state: #{token.state}" unless @places[token.state]
  raise "Token not in workflow" unless @tokens.include?(token)

  # Run any before_flow blocks
  @before_flows.each { |block| block.call(token) }

  # Check if transition is valid
  unless transition.from_state == token.state
    raise "Cannot fire transition '#{transition_name}' from state '#{token.state}'"
  end

  # Try to fire the transition
  unless transition.can_fire?(token)
    raise "Transition '#{transition_name}' cannot fire"
  end

  # Move token to new state
  @places[token.state].remove_token
  old_state = token.state
  token.state = transition.to_state
  @places[token.state].add_token(token)

  # Record the transition
  token.record_transition(transition_name, old_state, token.state)

  token
end

#states=(state_list) ⇒ Object



182
183
184
185
186
# File 'lib/circuit_breaker.rb', line 182

def states=(state_list)
  state_list.each do |state|
    @places[state] = Place.new(state)
  end
end