Class: SpotFlow::Execution
- Inherits:
-
Object
- Object
- SpotFlow::Execution
- Defined in:
- lib/spot_flow/execution.rb
Instance Attribute Summary collapse
-
#attached_to_id ⇒ Object
Returns the value of attribute attached_to_id.
-
#children ⇒ Object
Returns the value of attribute children.
-
#condition ⇒ Object
Returns the value of attribute condition.
-
#context ⇒ Object
Returns the value of attribute context.
-
#ended_at ⇒ Object
Returns the value of attribute ended_at.
-
#error_names ⇒ Object
Returns the value of attribute error_names.
-
#id ⇒ Object
Returns the value of attribute id.
-
#message_names ⇒ Object
Returns the value of attribute message_names.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#start_event_id ⇒ Object
Returns the value of attribute start_event_id.
-
#started_at ⇒ Object
Returns the value of attribute started_at.
-
#status ⇒ Object
Returns the value of attribute status.
-
#step ⇒ Object
Returns the value of attribute step.
-
#timer_expires_at ⇒ Object
Returns the value of attribute timer_expires_at.
-
#tokens_in ⇒ Object
Returns the value of attribute tokens_in.
-
#tokens_out ⇒ Object
Returns the value of attribute tokens_out.
-
#variables ⇒ Object
Returns the value of attribute variables.
Class Method Summary collapse
- .deserialize(json, context:) ⇒ Object
- .from_json(attributes, context:) ⇒ Object
- .start(context:, process:, variables: {}, start_event_id: nil, parent: nil) ⇒ Object
Instance Method Summary collapse
- #activated? ⇒ Boolean
- #as_json(_options = {}) ⇒ Object
- #attached_to ⇒ Object
- #call(process) ⇒ Object
- #check_expired_timers ⇒ Object
- #child_by_step_id(id) ⇒ Object
- #completed? ⇒ Boolean
- #continue ⇒ Object
- #end(notify_parent = false) ⇒ Object
- #ended? ⇒ Boolean
- #evaluate_condition(condition) ⇒ Object
- #evaluate_expression(expression, variables: parent&.variables || {}.with_indifferent_access) ⇒ Object
- #execute_step(step, attached_to: nil, sequence_flow: nil) ⇒ Object
- #execute_steps(steps) ⇒ Object
- #gen_uid ⇒ Object
-
#has_ended(_child) ⇒ Object
Called by the child step executors when they have ended.
-
#initialize(attributes = {}) ⇒ Execution
constructor
A new instance of Execution.
- #inspect ⇒ Object
- #invoke_listeners(type, sequence_flow = nil) ⇒ Object
- #run ⇒ Object
- #run_automated_tasks ⇒ Object
- #serialize ⇒ Object
- #signal(result = nil) ⇒ Object
- #start ⇒ Object
- #started? ⇒ Boolean
- #take(sequence_flow) ⇒ Object
- #take_all(sequence_flows) ⇒ Object
- #terminate ⇒ Object
- #terminated? ⇒ Boolean
- #throw_error(error_name, variables: {}) ⇒ Object
- #throw_message(message_name, variables: {}) ⇒ Object
- #tokens(active_tokens = []) ⇒ Object
- #wait ⇒ Object
- #waiting? ⇒ Boolean
- #waiting_automated_tasks ⇒ Object
- #waiting_children ⇒ Object
- #waiting_tasks ⇒ Object
Constructor Details
#initialize(attributes = {}) ⇒ Execution
Returns a new instance of Execution.
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/spot_flow/execution.rb', line 42 def initialize(attributes={}) attributes.each do |k, v| send("#{k}=", v) end @id ||= gen_uid @status ||= "activated" @variables = @variables&.with_indifferent_access || {}.with_indifferent_access @tokens_in ||= [] @tokens_out ||= [] @message_names ||= [] @error_names ||= [] @children ||= [] end |
Instance Attribute Details
#attached_to_id ⇒ Object
Returns the value of attribute attached_to_id.
6 7 8 |
# File 'lib/spot_flow/execution.rb', line 6 def attached_to_id @attached_to_id end |
#children ⇒ Object
Returns the value of attribute children.
6 7 8 |
# File 'lib/spot_flow/execution.rb', line 6 def children @children end |
#condition ⇒ Object
Returns the value of attribute condition.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def condition @condition end |
#context ⇒ Object
Returns the value of attribute context.
6 7 8 |
# File 'lib/spot_flow/execution.rb', line 6 def context @context end |
#ended_at ⇒ Object
Returns the value of attribute ended_at.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def ended_at @ended_at end |
#error_names ⇒ Object
Returns the value of attribute error_names.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def error_names @error_names end |
#id ⇒ Object
Returns the value of attribute id.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def id @id end |
#message_names ⇒ Object
Returns the value of attribute message_names.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def @message_names end |
#parent ⇒ Object
Returns the value of attribute parent.
6 7 8 |
# File 'lib/spot_flow/execution.rb', line 6 def parent @parent end |
#start_event_id ⇒ Object
Returns the value of attribute start_event_id.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def start_event_id @start_event_id end |
#started_at ⇒ Object
Returns the value of attribute started_at.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def started_at @started_at end |
#status ⇒ Object
Returns the value of attribute status.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def status @status end |
#step ⇒ Object
Returns the value of attribute step.
6 7 8 |
# File 'lib/spot_flow/execution.rb', line 6 def step @step end |
#timer_expires_at ⇒ Object
Returns the value of attribute timer_expires_at.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def timer_expires_at @timer_expires_at end |
#tokens_in ⇒ Object
Returns the value of attribute tokens_in.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def tokens_in @tokens_in end |
#tokens_out ⇒ Object
Returns the value of attribute tokens_out.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def tokens_out @tokens_out end |
#variables ⇒ Object
Returns the value of attribute variables.
5 6 7 |
# File 'lib/spot_flow/execution.rb', line 5 def variables @variables end |
Class Method Details
.deserialize(json, context:) ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'lib/spot_flow/execution.rb', line 17 def self.deserialize(json, context:) if json.is_a?(String) attributes = JSON.parse(json) else attributes = json end Execution.from_json(attributes, context: context) end |
.from_json(attributes, context:) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/spot_flow/execution.rb', line 26 def self.from_json(attributes, context:) step_id = attributes.delete("step_id") step_type = attributes.delete("step_type") step = step_type == "Process" ? context.process_by_id(step_id) : context.element_by_id(step_id) child_attributes = attributes.delete("children") Execution.new(attributes.merge(step: step, context:)).tap do |execution| execution.children = child_attributes.map do |ca| Execution.from_json(ca, context:).tap { |child| child.parent = execution } end if child_attributes end end |
.start(context:, process:, variables: {}, start_event_id: nil, parent: nil) ⇒ Object
10 11 12 13 14 15 |
# File 'lib/spot_flow/execution.rb', line 10 def self.start(context:, process:, variables: {}, start_event_id: nil, parent: nil) Execution.new(context: context, step: process, variables: variables, start_event_id: start_event_id, parent: parent).tap do |execution| context.executions.push execution execution.start end end |
Instance Method Details
#activated? ⇒ Boolean
64 65 66 |
# File 'lib/spot_flow/execution.rb', line 64 def activated? status == "activated" end |
#as_json(_options = {}) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/spot_flow/execution.rb', line 242 def as_json( = {}) { id: id, step_id: step&.id, step_type: step&.class&.name&.demodulize, attached_to_id: attached_to_id, status: status, started_at: started_at, ended_at: ended_at, variables: variables.as_json, tokens_in: tokens_in, tokens_out: tokens_out, message_names: , error_names: error_names, timer_expires_at: timer_expires_at, condition: condition, children: children.map { |child| child.as_json }, }.transform_values(&:presence).compact end |
#attached_to ⇒ Object
209 210 211 |
# File 'lib/spot_flow/execution.rb', line 209 def attached_to @attached_to ||= parent.children.find { |child| child.id == attached_to_id } if parent end |
#call(process) ⇒ Object
197 198 199 |
# File 'lib/spot_flow/execution.rb', line 197 def call(process) execute_step(process, attached_to: self) end |
#check_expired_timers ⇒ Object
169 170 171 |
# File 'lib/spot_flow/execution.rb', line 169 def check_expired_timers waiting_children.each { |child| child.signal if child.timer_expires_at.present? && Time.zone.now > child.timer_expires_at } end |
#child_by_step_id(id) ⇒ Object
213 214 215 |
# File 'lib/spot_flow/execution.rb', line 213 def child_by_step_id(id) children.find { |child| child.step.id == id } end |
#completed? ⇒ Boolean
72 73 74 |
# File 'lib/spot_flow/execution.rb', line 72 def completed? status == "completed" end |
#continue ⇒ Object
104 105 106 |
# File 'lib/spot_flow/execution.rb', line 104 def continue step.execute(self) end |
#end(notify_parent = false) ⇒ Object
118 119 120 121 122 123 124 125 126 127 |
# File 'lib/spot_flow/execution.rb', line 118 def end(notify_parent = false) @status = "completed" unless status == "terminated" map_output_variables if step&.output_mappings&.present? parent.variables.merge!(variables) if parent && variables.present? @ended_at = Time.zone.now context.notify_listener(:execution_ended, execution: self) children.each { |child| child.terminate unless child.ended? } parent.children.each { |child| child.terminate if child.attached_to == self && child.waiting? } if parent parent.has_ended(self) if parent && notify_parent end |
#ended? ⇒ Boolean
60 61 62 |
# File 'lib/spot_flow/execution.rb', line 60 def ended? ended_at.present? end |
#evaluate_condition(condition) ⇒ Object
173 174 175 |
# File 'lib/spot_flow/execution.rb', line 173 def evaluate_condition(condition) evaluate_expression(condition.delete_prefix("=")) == true end |
#evaluate_expression(expression, variables: parent&.variables || {}.with_indifferent_access) ⇒ Object
177 178 179 |
# File 'lib/spot_flow/execution.rb', line 177 def evaluate_expression(expression, variables: parent&.variables || {}.with_indifferent_access) SpotFeel.evaluate(expression.delete_prefix("="), variables:) end |
#execute_step(step, attached_to: nil, sequence_flow: nil) ⇒ Object
84 85 86 87 88 89 |
# File 'lib/spot_flow/execution.rb', line 84 def execute_step(step, attached_to: nil, sequence_flow: nil) child_execution = children.find { |child| child.step.id == step.id } child_execution = Execution.new(context: context, step: step, parent: self, attached_to_id: attached_to&.id).tap { |ce| children.push ce } unless child_execution child_execution.tokens_in += [sequence_flow.id] if sequence_flow child_execution.start end |
#execute_steps(steps) ⇒ Object
80 81 82 |
# File 'lib/spot_flow/execution.rb', line 80 def execute_steps(steps) steps.each { |step| execute_step(step) } end |
#gen_uid ⇒ Object
38 39 40 |
# File 'lib/spot_flow/execution.rb', line 38 def gen_uid rand(36**8).to_s(36) end |
#has_ended(_child) ⇒ Object
Called by the child step executors when they have ended
204 205 206 207 |
# File 'lib/spot_flow/execution.rb', line 204 def has_ended(_child) step.leave(self) if step.is_a?(SpotFlow::Bpmn::SubProcess) || step.is_a?(SpotFlow::Bpmn::CallActivity) self.end(true) end |
#inspect ⇒ Object
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/spot_flow/execution.rb', line 262 def inspect parts = ["#<Execution @id=#{id.inspect}"] parts << "@step_type=#{step&.class&.name&.demodulize}" if step parts << "@step_id=#{step.id.inspect}" if step parts << "@status=#{status.inspect}" if status parts << "@started_at=#{started_at.inspect}" if started_at parts << "@ended_at=#{ended_at.inspect}" if ended_at parts << "@attached_to_id=#{attached_to_id.inspect}" if attached_to_id parts << "@variables=#{variables.inspect}" if variables.present? # parts << "@tokens_in=#{tokens_in.inspect}" if tokens_in.present? # parts << "@tokens_out=#{tokens_out.inspect}" if tokens_out.present? parts << "@message_names=#{.inspect}" if .present? parts << "@error_names=#{error_names.inspect}" if error_names.present? parts << "@timer_expires_at=#{timer_expires_at.inspect}" if timer_expires_at parts << "@condition=#{condition.inspect}" if condition parts << "@children=#{children.inspect}" if children.present? parts.join(" ") + ">" end |
#invoke_listeners(type, sequence_flow = nil) ⇒ Object
91 92 93 |
# File 'lib/spot_flow/execution.rb', line 91 def invoke_listeners(type, sequence_flow = nil) context.listeners.each { |listener| listener[type].call(self, sequence_flow) if listener[type] } end |
#run ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/spot_flow/execution.rb', line 185 def run return unless step.is_automated? result = step.run(self) if result.present? signal(result) else wait end end |
#run_automated_tasks ⇒ Object
181 182 183 |
# File 'lib/spot_flow/execution.rb', line 181 def run_automated_tasks waiting_automated_tasks.each { |child| child.run } end |
#serialize ⇒ Object
238 239 240 |
# File 'lib/spot_flow/execution.rb', line 238 def serialize(...) to_json(...) end |
#signal(result = nil) ⇒ Object
141 142 143 144 145 |
# File 'lib/spot_flow/execution.rb', line 141 def signal(result = nil) @variables.merge!(result_to_variables(result)) if result.present? raise ExecutionError.new("Cannot signal a step execution that has ended.") if ended? step.signal(self) end |
#start ⇒ Object
95 96 97 98 99 100 101 102 |
# File 'lib/spot_flow/execution.rb', line 95 def start @status = "started" @started_at = Time.zone.now map_input_variables if step&.input_mappings&.present? context.notify_listener(:execution_started, execution: self) step..each { || parent.execute_step(, attached_to: self) } if step.is_a?(SpotFlow::Bpmn::Activity) continue end |
#started? ⇒ Boolean
56 57 58 |
# File 'lib/spot_flow/execution.rb', line 56 def started? started_at.present? end |
#take(sequence_flow) ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/spot_flow/execution.rb', line 133 def take(sequence_flow) to_step = sequence_flow.target tokens_out.push sequence_flow.id tokens_out.uniq! context.notify_listener(:flow_taken, execution: self, sequence_flow: sequence_flow) parent.execute_step(to_step, sequence_flow: sequence_flow) end |
#take_all(sequence_flows) ⇒ Object
129 130 131 |
# File 'lib/spot_flow/execution.rb', line 129 def take_all(sequence_flows) sequence_flows.each { |sequence_flow| take(sequence_flow) } end |
#terminate ⇒ Object
113 114 115 116 |
# File 'lib/spot_flow/execution.rb', line 113 def terminate @status = "terminated" self.end end |
#terminated? ⇒ Boolean
76 77 78 |
# File 'lib/spot_flow/execution.rb', line 76 def terminated? status == "terminated" end |
#throw_error(error_name, variables: {}) ⇒ Object
158 159 160 161 162 163 164 165 166 167 |
# File 'lib/spot_flow/execution.rb', line 158 def throw_error(error_name, variables: {}) waiting_children.each do |child| step = child.step if step.is_a?(SpotFlow::Bpmn::Event) && step.error_event_definitions.any? { |error_event_definition| error_event_definition.error_name == error_name } child.signal(variables) break end end context.notify_listener(:error_thrown, execution: self, error_name: error_name) end |
#throw_message(message_name, variables: {}) ⇒ Object
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/spot_flow/execution.rb', line 147 def (, variables: {}) waiting_children.each do |child| step = child.step if step.is_a?(SpotFlow::Bpmn::Event) && step..any? { || . == } child.signal(variables) break end end context.notify_listener(:message_thrown, execution: self, message_name: ) end |
#tokens(active_tokens = []) ⇒ Object
229 230 231 232 233 234 235 236 |
# File 'lib/spot_flow/execution.rb', line 229 def tokens(active_tokens = []) children.each do |child| active_tokens = active_tokens + child.tokens_out active_tokens = active_tokens - child.tokens_in if child.ended? active_tokens = active_tokens + child.tokens(active_tokens) end active_tokens.uniq end |
#wait ⇒ Object
108 109 110 111 |
# File 'lib/spot_flow/execution.rb', line 108 def wait @status = "waiting" context.notify_listener(:execution_waited, execution: self) end |
#waiting? ⇒ Boolean
68 69 70 |
# File 'lib/spot_flow/execution.rb', line 68 def waiting? status == "waiting" end |
#waiting_automated_tasks ⇒ Object
225 226 227 |
# File 'lib/spot_flow/execution.rb', line 225 def waiting_automated_tasks waiting_tasks.select { |child| child.step.is_automated? } end |
#waiting_children ⇒ Object
217 218 219 |
# File 'lib/spot_flow/execution.rb', line 217 def waiting_children children.filter { |child| child.waiting? } end |