Class: ExcADG::StateMachine
- Inherits:
-
Object
- Object
- ExcADG::StateMachine
- Defined in:
- lib/excadg/state_machine.rb
Overview
carry states and transitions for individual vertices
Defined Under Namespace
Classes: NotAllTransitionsBound, WrongState, WrongTransition
Constant Summary collapse
- GRAPH =
sets in stone possible state transitions
RGL::DirectedAdjacencyGraph.new
Instance Method Summary collapse
- #assert_state_transition_bounds ⇒ Object
-
#bind_action(source, target, &block) ⇒ Object
bind action to one of the state graph’s edges.
-
#initialize(name:) ⇒ StateMachine
constructor
add states graph to the current object.
-
#state_data ⇒ Object
makes state data for the current vertex.
-
#step ⇒ Object
transition to next state @return: state data (result) / nil if it’s a final step.
Constructor Details
#initialize(name:) ⇒ StateMachine
add states graph to the current object
23 24 25 26 27 28 29 |
# File 'lib/excadg/state_machine.rb', line 23 def initialize name: @state = :new @state_edge_bindings = {} @state_transition_data = {} @name = name end |
Instance Method Details
#assert_state_transition_bounds ⇒ Object
76 77 78 |
# File 'lib/excadg/state_machine.rb', line 76 def assert_state_transition_bounds raise NotAllTransitionsBound, GRAPH.edges - @state_edge_bindings.keys unless GRAPH.edges.eql? @state_edge_bindings.keys end |
#bind_action(source, target, &block) ⇒ Object
bind action to one of the state graph’s edges
32 33 34 35 36 37 38 39 40 |
# File 'lib/excadg/state_machine.rb', line 32 def bind_action source, target, &block [source, target].each { |state| raise WrongState, "unknown state #{state}" unless GRAPH.has_vertex? state } raise WrongTransition.new source, target unless GRAPH.has_edge? source, target edge = GRAPH.edges.find { |e| e.source == source && e.target = target } @state_edge_bindings[edge] = block end |
#state_data ⇒ Object
makes state data for the current vertex
81 82 83 |
# File 'lib/excadg/state_machine.rb', line 81 def state_data VStateData::Full.new name: @name, data: @state_transition_data[@state], state: @state end |
#step ⇒ Object
transition to next state @return: state data (result) / nil if it’s a final step
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/excadg/state_machine.rb', line 44 def step Log.debug 'taking another step' assert_state_transition_bounds target_candidates = GRAPH.each_adjacent @state Log.debug "possible candidates: #{target_candidates.size}" return nil if target_candidates.none? raise WrongState, "state #{@state} has more than one adjacent states" unless target_candidates.one? target = target_candidates.first Log.debug "found a candidate: #{target}" edge = GRAPH.edges.find { |e| e.source == @state && e.target = target } begin @state_transition_data[target] = @state_edge_bindings[edge].call @state = target Log.debug "moved to #{@state}" rescue StandardError => e Log.error "step failed with #{e} / #{e.backtrace}" @state_transition_data[:failed] = e @state = :failed ensure begin Broker.ask Request::Update.new data: state_data rescue StandardError => e @state_transition_data[:failed] = e @state = :failed Broker.ask Request::Update.new data: state_data end end @state_transition_data[@state] end |