floe 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/floe/workflow.rb CHANGED
@@ -12,9 +12,26 @@ module Floe
12
12
  payload = path_or_io.respond_to?(:read) ? path_or_io.read : File.read(path_or_io)
13
13
  new(payload, context, credentials)
14
14
  end
15
+
16
+ def wait(workflows, timeout: 5)
17
+ logger.info("checking #{workflows.count} workflows...")
18
+
19
+ start = Time.now.utc
20
+ ready = []
21
+
22
+ loop do
23
+ ready = workflows.select(&:step_nonblock_ready?)
24
+ break if timeout.zero? || Time.now.utc - start > timeout || !ready.empty?
25
+
26
+ sleep(1)
27
+ end
28
+
29
+ logger.info("checking #{workflows.count} workflows...Complete - #{ready.count} ready")
30
+ ready
31
+ end
15
32
  end
16
33
 
17
- attr_reader :context, :credentials, :output, :payload, :states, :states_by_name, :current_state, :status
34
+ attr_reader :context, :credentials, :payload, :states, :states_by_name, :start_at
18
35
 
19
36
  def initialize(payload, context = nil, credentials = {})
20
37
  payload = JSON.parse(payload) if payload.kind_of?(String)
@@ -24,62 +41,69 @@ module Floe
24
41
  @payload = payload
25
42
  @context = context
26
43
  @credentials = credentials
44
+ @start_at = payload["StartAt"]
27
45
 
28
46
  @states = payload["States"].to_a.map { |name, state| State.build!(self, name, state) }
29
47
  @states_by_name = @states.each_with_object({}) { |state, result| result[state.name] = state }
30
- start_at = @payload["StartAt"]
31
-
32
- context.state["Name"] ||= start_at
33
-
34
- current_state_name = context.state["Name"]
35
- @current_state = @states_by_name[current_state_name]
36
48
 
37
- @status = current_state_name == start_at ? "pending" : current_state.status
49
+ unless context.state.key?("Name")
50
+ context.state["Name"] = start_at
51
+ context.state["Input"] = context.execution["Input"].dup
52
+ end
38
53
  rescue JSON::ParserError => err
39
54
  raise Floe::InvalidWorkflowError, err.message
40
55
  end
41
56
 
42
- def step
43
- @status = "running" if @status == "pending"
44
- context.execution["StartTime"] ||= Time.now.utc
45
-
46
- context.state["Guid"] = SecureRandom.uuid
47
- context.state["Input"] ||= context.execution["Input"].dup
57
+ def run!
58
+ step until end?
59
+ self
60
+ end
48
61
 
49
- logger.info("Running state: [#{current_state.name}] with input [#{context.state["Input"]}]...")
62
+ def step
63
+ step_nonblock_wait until step_nonblock == 0
64
+ self
65
+ end
50
66
 
51
- context.state["EnteredTime"] = Time.now.utc
67
+ def run_nonblock
68
+ loop while step_nonblock == 0 && !end?
69
+ self
70
+ end
52
71
 
53
- tick = Process.clock_gettime(Process::CLOCK_MONOTONIC)
54
- next_state, output = current_state.run!(context.state["Input"])
55
- tock = Process.clock_gettime(Process::CLOCK_MONOTONIC)
72
+ def step_nonblock
73
+ return Errno::EPERM if end?
56
74
 
57
- context.state["FinishedTime"] = Time.now.utc
58
- context.state["Duration"] = (tock - tick) / 1_000_000.0
59
- context.state["Output"] = output
75
+ step_next
76
+ current_state.run_nonblock!
77
+ end
60
78
 
61
- logger.info("Running state: [#{current_state.name}] with input [#{context["Input"]}]...Complete - next state: [#{next_state}] output: [#{output}]")
79
+ def step_nonblock_wait(timeout: 5)
80
+ current_state.run_wait(:timeout => timeout)
81
+ end
62
82
 
63
- context.states << context.state
83
+ def step_nonblock_ready?
84
+ current_state.ready?
85
+ end
64
86
 
65
- @status = current_state.status
66
- @current_state = next_state && @states_by_name[next_state]
67
- @output = output if end?
87
+ def status
88
+ context.status
89
+ end
68
90
 
69
- context.state = {"Name" => next_state, "Input" => output} unless end?
91
+ def output
92
+ context.output if end?
93
+ end
70
94
 
71
- self
95
+ def end?
96
+ context.ended?
72
97
  end
73
98
 
74
- def run!
75
- until end?
76
- step
77
- end
78
- self
99
+ def current_state
100
+ @states_by_name[context.state_name]
79
101
  end
80
102
 
81
- def end?
82
- current_state.nil?
103
+ private
104
+
105
+ def step_next
106
+ context.state = {"Name" => context.next_state, "Input" => context.output} if context.next_state
83
107
  end
84
108
  end
85
109
  end
data/lib/floe.rb CHANGED
@@ -8,7 +8,9 @@ require_relative "floe/logging"
8
8
  require_relative "floe/workflow"
9
9
  require_relative "floe/workflow/catcher"
10
10
  require_relative "floe/workflow/choice_rule"
11
- require_relative "floe/workflow/choice_rule/boolean"
11
+ require_relative "floe/workflow/choice_rule/not"
12
+ require_relative "floe/workflow/choice_rule/or"
13
+ require_relative "floe/workflow/choice_rule/and"
12
14
  require_relative "floe/workflow/choice_rule/data"
13
15
  require_relative "floe/workflow/context"
14
16
  require_relative "floe/workflow/path"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: floe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Developers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-07 00:00:00.000000000 Z
11
+ date: 2023-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_spawn
@@ -80,48 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.0'
83
- - !ruby/object:Gem::Dependency
84
- name: manageiq-style
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rspec
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
83
  description: Simple Workflow Runner.
126
84
  email:
127
85
  executables:
@@ -148,8 +106,10 @@ files:
148
106
  - lib/floe/workflow.rb
149
107
  - lib/floe/workflow/catcher.rb
150
108
  - lib/floe/workflow/choice_rule.rb
151
- - lib/floe/workflow/choice_rule/boolean.rb
109
+ - lib/floe/workflow/choice_rule/and.rb
152
110
  - lib/floe/workflow/choice_rule/data.rb
111
+ - lib/floe/workflow/choice_rule/not.rb
112
+ - lib/floe/workflow/choice_rule/or.rb
153
113
  - lib/floe/workflow/context.rb
154
114
  - lib/floe/workflow/path.rb
155
115
  - lib/floe/workflow/payload_template.rb
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Floe
4
- class Workflow
5
- class ChoiceRule
6
- class Boolean < Floe::Workflow::ChoiceRule
7
- def true?(context, input)
8
- if payload.key?("Not")
9
- !ChoiceRule.true?(payload["Not"], context, input)
10
- elsif payload.key?("And")
11
- payload["And"].all? { |choice| ChoiceRule.true?(choice, context, input) }
12
- else
13
- payload["Or"].any? { |choice| ChoiceRule.true?(choice, context, input) }
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end