dwf 0.1.10 → 0.1.11
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +67 -0
- data/README.md +117 -33
- data/dwf.gemspec +4 -2
- data/lib/dwf/callback.rb +13 -10
- data/lib/dwf/client.rb +50 -9
- data/lib/dwf/concerns/checkable.rb +29 -0
- data/lib/dwf/errors.rb +3 -1
- data/lib/dwf/item.rb +41 -33
- data/lib/dwf/utils.rb +6 -0
- data/lib/dwf/version.rb +1 -1
- data/lib/dwf/workflow.rb +119 -24
- data/spec/dwf/client_spec.rb +77 -3
- data/spec/dwf/item_spec.rb +49 -10
- data/spec/dwf/utils_spec.rb +9 -0
- data/spec/dwf/workflow_spec.rb +178 -13
- data/spec/spec_helper.rb +3 -0
- metadata +27 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e545ff4c6f4b56071875f642f1262fee7762fabb63d86c816a0c943cb8e34657
|
4
|
+
data.tar.gz: dfe832f98724b81b8ff1198320cb66013869cca6ba2b2f89d47c4caf0b2108f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e77ca9abe614aa1da026818f1a49028bcc3878bd9bd5838e8cdfdf245ab09d124ab4300bd077eed1c3e8b07e46b321c1dd59d18face658fda3f6c636e28954f
|
7
|
+
data.tar.gz: 6a6ff8756a13fcec73966c41ded7b808cae24a73e1cec2bd301dacfdbfde6022812c7f27c6dacc12a5bb469aae241e59316eb544b2ca7ac1f0530e1c5f5ffa2c
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,72 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
|
+
## 0.1.11
|
4
|
+
### Added
|
5
|
+
#### Subworkflow - Only support sidekiq pro
|
6
|
+
There might be a case when you want to reuse a workflow in another workflow
|
7
|
+
|
8
|
+
As an example, let's write a workflow which contain another workflow, expected that the SubWorkflow workflow execute after `SecondItem` and the `ThirdItem` execute after `SubWorkflow`
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'dwf', '~> 0.1.11'
|
12
|
+
```
|
13
|
+
|
14
|
+
### Setup
|
15
|
+
```ruby
|
16
|
+
class FirstItem < Dwf::Item
|
17
|
+
def perform
|
18
|
+
puts "Main flow: #{self.class.name} running"
|
19
|
+
puts "Main flow: #{self.class.name} finish"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
SecondItem = Class.new(FirstItem)
|
24
|
+
ThirtItem = Class.new(FirstItem)
|
25
|
+
|
26
|
+
class FirstSubItem < Dwf::Item
|
27
|
+
def perform
|
28
|
+
puts "Sub flow: #{self.class.name} running"
|
29
|
+
puts "Sub flow: #{self.class.name} finish"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
SecondSubItem = Class.new(FirstSubItem)
|
34
|
+
|
35
|
+
class SubWorkflow < Dwf::Workflow
|
36
|
+
def configure
|
37
|
+
run FirstSubItem
|
38
|
+
run SecondSubItem, after: FirstSubItem
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class TestWf < Dwf::Workflow
|
44
|
+
def configure
|
45
|
+
run FirstItem
|
46
|
+
run SecondItem, after: FirstItem
|
47
|
+
run SubWorkflow, after: SecondItem
|
48
|
+
run ThirtItem, after: SubWorkflow
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
wf = TestWf.create
|
53
|
+
wf.start!
|
54
|
+
```
|
55
|
+
|
56
|
+
### Result
|
57
|
+
```
|
58
|
+
Main flow: FirstItem running
|
59
|
+
Main flow: FirstItem finish
|
60
|
+
Main flow: SecondItem running
|
61
|
+
Main flow: SecondItem finish
|
62
|
+
Sub flow: FirstSubItem running
|
63
|
+
Sub flow: FirstSubItem finish
|
64
|
+
Sub flow: SecondSubItem running
|
65
|
+
Sub flow: SecondSubItem finish
|
66
|
+
Main flow: ThirtItem running
|
67
|
+
Main flow: ThirtItem finish
|
68
|
+
```
|
69
|
+
|
3
70
|
## 0.1.10
|
4
71
|
### Added
|
5
72
|
- Allow to use argument within workflow and update the defining callback way
|
data/README.md
CHANGED
@@ -4,22 +4,45 @@
|
|
4
4
|
# Installation
|
5
5
|
## 1. Add `dwf` to Gemfile
|
6
6
|
```ruby
|
7
|
-
gem 'dwf', '~> 0.1.
|
7
|
+
gem 'dwf', '~> 0.1.10'
|
8
8
|
```
|
9
|
-
## 2. Execute flow
|
9
|
+
## 2. Execute flow example
|
10
10
|
### Declare jobs
|
11
11
|
|
12
12
|
```ruby
|
13
13
|
require 'dwf'
|
14
14
|
|
15
|
-
class
|
15
|
+
class FirstItem < Dwf::Item
|
16
16
|
def perform
|
17
|
-
puts "#{self.class.name}
|
18
|
-
|
19
|
-
puts params
|
20
|
-
puts "#{self.class.name} Finished"
|
17
|
+
puts "#{self.class.name}: running"
|
18
|
+
puts "#{self.class.name}: finish"
|
21
19
|
end
|
22
20
|
end
|
21
|
+
|
22
|
+
class SecondItem < Dwf::Item
|
23
|
+
def perform
|
24
|
+
puts "#{self.class.name}: running"
|
25
|
+
output('Send to ThirdItem')
|
26
|
+
puts "#{self.class.name} finish"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ThirdItem < Dwf::Item
|
31
|
+
def perform
|
32
|
+
puts "#{self.class.name}: running"
|
33
|
+
puts "#{self.class.name}: finish"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class FourthItem < Dwf::Item
|
38
|
+
def perform
|
39
|
+
puts "#{self.class.name}: running"
|
40
|
+
puts "payloads from incoming: #{payloads.inspect}"
|
41
|
+
puts "#{self.class.name}: finish"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
FifthItem = Class.new(FirstItem)
|
23
46
|
```
|
24
47
|
|
25
48
|
### Declare flow
|
@@ -28,16 +51,18 @@ require 'dwf'
|
|
28
51
|
|
29
52
|
class TestWf < Dwf::Workflow
|
30
53
|
def configure
|
31
|
-
run
|
32
|
-
run
|
33
|
-
run
|
34
|
-
run
|
35
|
-
run
|
36
|
-
run F, params: 'F say hello'
|
54
|
+
run FirstItem
|
55
|
+
run SecondItem, after: FirstItem
|
56
|
+
run ThirdItem, after: FirstItem
|
57
|
+
run FourthItem, after: [ThirdItem, SecondItem]
|
58
|
+
run FifthItem, after: FourthItem
|
37
59
|
end
|
38
60
|
end
|
39
61
|
```
|
40
|
-
|
62
|
+
### Start background worker process
|
63
|
+
```
|
64
|
+
bundle exec sidekiq -q dwf
|
65
|
+
```
|
41
66
|
|
42
67
|
### Execute flow
|
43
68
|
```ruby
|
@@ -55,21 +80,16 @@ By default `dwf` will use `Dwf::Workflow::BUILD_IN` callback.
|
|
55
80
|
|
56
81
|
### Output
|
57
82
|
```
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
E say hello
|
69
|
-
E Finished
|
70
|
-
D Working
|
71
|
-
D say hello
|
72
|
-
D Finished
|
83
|
+
FirstItem: running
|
84
|
+
FirstItem: finish
|
85
|
+
SecondItem: running
|
86
|
+
SecondItem finish
|
87
|
+
ThirdItem: running
|
88
|
+
ThirdItem: finish
|
89
|
+
FourthItem: running
|
90
|
+
FourthItem: finish
|
91
|
+
FifthItem: running
|
92
|
+
FifthItem: finish
|
73
93
|
```
|
74
94
|
|
75
95
|
# Config redis and default queue
|
@@ -84,8 +104,8 @@ Dwf.config do |config|
|
|
84
104
|
config.namespace = 'dwf'
|
85
105
|
end
|
86
106
|
```
|
87
|
-
|
88
|
-
|
107
|
+
# Advanced features
|
108
|
+
## Pipelining
|
89
109
|
You can pass jobs result to next nodes
|
90
110
|
|
91
111
|
```ruby
|
@@ -118,6 +138,70 @@ end
|
|
118
138
|
}
|
119
139
|
]
|
120
140
|
```
|
141
|
+
## Subworkflow - Only support sidekiq pro
|
142
|
+
There might be a case when you want to reuse a workflow in another workflow
|
143
|
+
|
144
|
+
As an example, let's write a workflow which contain another workflow, expected that the SubWorkflow workflow execute after `SecondItem` and the `ThirdItem` execute after `SubWorkflow`
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
gem 'dwf', '~> 0.1.11'
|
148
|
+
```
|
149
|
+
|
150
|
+
### Setup
|
151
|
+
```ruby
|
152
|
+
class FirstItem < Dwf::Item
|
153
|
+
def perform
|
154
|
+
puts "Main flow: #{self.class.name} running"
|
155
|
+
puts "Main flow: #{self.class.name} finish"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
SecondItem = Class.new(FirstItem)
|
160
|
+
ThirtItem = Class.new(FirstItem)
|
161
|
+
|
162
|
+
class FirstSubItem < Dwf::Item
|
163
|
+
def perform
|
164
|
+
puts "Sub flow: #{self.class.name} running"
|
165
|
+
puts "Sub flow: #{self.class.name} finish"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
SecondSubItem = Class.new(FirstSubItem)
|
170
|
+
|
171
|
+
class SubWorkflow < Dwf::Workflow
|
172
|
+
def configure
|
173
|
+
run FirstSubItem
|
174
|
+
run SecondSubItem, after: FirstSubItem
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
class TestWf < Dwf::Workflow
|
180
|
+
def configure
|
181
|
+
run FirstItem
|
182
|
+
run SecondItem, after: FirstItem
|
183
|
+
run SubWorkflow, after: SecondItem
|
184
|
+
run ThirtItem, after: SubWorkflow
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
wf = TestWf.create
|
189
|
+
wf.start!
|
190
|
+
```
|
191
|
+
|
192
|
+
### Result
|
193
|
+
```
|
194
|
+
Main flow: FirstItem running
|
195
|
+
Main flow: FirstItem finish
|
196
|
+
Main flow: SecondItem running
|
197
|
+
Main flow: SecondItem finish
|
198
|
+
Sub flow: FirstSubItem running
|
199
|
+
Sub flow: FirstSubItem finish
|
200
|
+
Sub flow: SecondSubItem running
|
201
|
+
Sub flow: SecondSubItem finish
|
202
|
+
Main flow: ThirtItem running
|
203
|
+
Main flow: ThirtItem finish
|
204
|
+
```
|
121
205
|
|
122
206
|
# Todo
|
123
207
|
- [x] Make it work
|
@@ -125,9 +209,9 @@ end
|
|
125
209
|
- [x] Support with build-in callback
|
126
210
|
- [x] Add github workflow
|
127
211
|
- [x] Redis configurable
|
128
|
-
- [x]
|
212
|
+
- [x] Pipelining
|
129
213
|
- [X] Test
|
130
|
-
- [ ]
|
214
|
+
- [ ] WIP - subworkflow
|
131
215
|
- [ ] Support [Resque](https://github.com/resque/resque)
|
132
216
|
- [ ] Key value store plugable
|
133
217
|
- [ ] research https://github.com/moneta-rb/moneta
|
data/dwf.gemspec
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
lib = File.expand_path('../lib', __FILE__)
|
5
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require_relative 'lib/dwf/version'
|
6
7
|
|
7
8
|
Gem::Specification.new do |spec|
|
8
9
|
spec.name = "dwf"
|
9
|
-
spec.version =
|
10
|
+
spec.version = Dwf::VERSION
|
10
11
|
spec.authors = ["dthtien"]
|
11
12
|
spec.email = ["tiendt2311@gmail.com"]
|
12
13
|
|
@@ -25,8 +26,9 @@ Gem::Specification.new do |spec|
|
|
25
26
|
# guide at: https://bundler.io/guides/creating_gem.html
|
26
27
|
|
27
28
|
spec.add_development_dependency 'byebug', '~> 11.1.3'
|
29
|
+
spec.add_development_dependency 'mock_redis', '~> 0.27.2'
|
28
30
|
spec.add_dependency 'redis', '~> 4.2.0'
|
29
31
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
30
|
-
spec.add_development_dependency 'mock_redis', '~> 0.27.2'
|
31
32
|
spec.add_dependency 'sidekiq', '~> 6.2.0'
|
33
|
+
spec.add_development_dependency 'simplecov'
|
32
34
|
end
|
data/lib/dwf/callback.rb
CHANGED
@@ -9,8 +9,8 @@ module Dwf
|
|
9
9
|
previous_job_names = options['names']
|
10
10
|
workflow_id = options['workflow_id']
|
11
11
|
processing_job_names = previous_job_names.map do |job_name|
|
12
|
-
|
13
|
-
|
12
|
+
node = client.find_node(job_name, workflow_id)
|
13
|
+
node.outgoing
|
14
14
|
end.flatten.uniq
|
15
15
|
return if processing_job_names.empty?
|
16
16
|
|
@@ -19,7 +19,7 @@ module Dwf
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def start(job)
|
22
|
-
job.outgoing.any? ? start_with_batch(job) : job.
|
22
|
+
job.outgoing.any? ? start_with_batch(job) : job.persist_and_perform_async!
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
@@ -40,11 +40,13 @@ module Dwf
|
|
40
40
|
batch.on(
|
41
41
|
:success,
|
42
42
|
'Dwf::Callback#process_next_step',
|
43
|
-
names: jobs.map(&:
|
43
|
+
names: jobs.map(&:name),
|
44
44
|
workflow_id: workflow_id
|
45
45
|
)
|
46
46
|
batch.jobs do
|
47
|
-
jobs.each
|
47
|
+
jobs.each do |job|
|
48
|
+
job.persist_and_perform_async! if job.ready_to_start?
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -61,7 +63,7 @@ module Dwf
|
|
61
63
|
|
62
64
|
def fetch_jobs(processing_job_names, workflow_id)
|
63
65
|
processing_job_names.map do |job_name|
|
64
|
-
client.
|
66
|
+
client.find_node(job_name, workflow_id)
|
65
67
|
end.compact
|
66
68
|
end
|
67
69
|
|
@@ -71,15 +73,16 @@ module Dwf
|
|
71
73
|
client.release_lock(workflow_id, job_name)
|
72
74
|
end
|
73
75
|
|
74
|
-
def start_with_batch(
|
76
|
+
def start_with_batch(node)
|
75
77
|
batch = Sidekiq::Batch.new
|
78
|
+
workflow_id = node.is_a?(Dwf::Workflow) ? node.parent_id : node.workflow_id
|
76
79
|
batch.on(
|
77
80
|
:success,
|
78
81
|
'Dwf::Callback#process_next_step',
|
79
|
-
names: [
|
80
|
-
workflow_id:
|
82
|
+
names: [node.name],
|
83
|
+
workflow_id: workflow_id
|
81
84
|
)
|
82
|
-
batch.jobs {
|
85
|
+
batch.jobs { node.persist_and_perform_async! }
|
83
86
|
end
|
84
87
|
|
85
88
|
def client
|
data/lib/dwf/client.rb
CHANGED
@@ -22,8 +22,22 @@ module Dwf
|
|
22
22
|
Dwf::Item.from_hash(Dwf::Utils.symbolize_keys(data))
|
23
23
|
end
|
24
24
|
|
25
|
+
def find_node(name, workflow_id)
|
26
|
+
if Utils.workflow_name?(name)
|
27
|
+
if name.include?('|')
|
28
|
+
_, id = name.split('|')
|
29
|
+
else
|
30
|
+
id = workflow_id(name, workflow_id)
|
31
|
+
end
|
32
|
+
find_workflow(id)
|
33
|
+
else
|
34
|
+
find_job(workflow_id, name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
25
38
|
def find_workflow(id)
|
26
|
-
|
39
|
+
key = redis.keys("dwf.workflows.#{id}*").first
|
40
|
+
data = redis.get(key)
|
27
41
|
raise WorkflowNotFound, "Workflow with given id doesn't exist" if data.nil?
|
28
42
|
|
29
43
|
hash = JSON.parse(data)
|
@@ -32,6 +46,19 @@ module Dwf
|
|
32
46
|
workflow_from_hash(hash, nodes)
|
33
47
|
end
|
34
48
|
|
49
|
+
def find_sub_workflow(name, parent_id)
|
50
|
+
find_workflow(workflow_id(name, parent_id))
|
51
|
+
end
|
52
|
+
|
53
|
+
def sub_workflows(id)
|
54
|
+
keys = redis.keys("dwf.workflows.*.*.#{id}")
|
55
|
+
keys.map do |key|
|
56
|
+
id = key.split('.')[2]
|
57
|
+
|
58
|
+
find_workflow(id)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
35
62
|
def persist_job(job)
|
36
63
|
redis.hset("dwf.jobs.#{job.workflow_id}.#{job.klass}", job.id, job.as_json)
|
37
64
|
end
|
@@ -51,7 +78,10 @@ module Dwf
|
|
51
78
|
end
|
52
79
|
|
53
80
|
def persist_workflow(workflow)
|
54
|
-
|
81
|
+
key = [
|
82
|
+
'dwf', 'workflows', workflow.id, workflow.class.name, workflow.parent_id
|
83
|
+
].compact.join('.')
|
84
|
+
redis.set(key, workflow.as_json)
|
55
85
|
end
|
56
86
|
|
57
87
|
def build_job_id(workflow_id, job_klass)
|
@@ -96,6 +126,13 @@ module Dwf
|
|
96
126
|
|
97
127
|
private
|
98
128
|
|
129
|
+
def workflow_id(name, parent_id)
|
130
|
+
key = redis.keys("dwf.workflows.*.#{name}.#{parent_id}").first
|
131
|
+
return if key.nil?
|
132
|
+
|
133
|
+
key.split('.')[2]
|
134
|
+
end
|
135
|
+
|
99
136
|
def find_job_by_klass_and_id(workflow_id, job_name)
|
100
137
|
job_klass, job_id = job_name.split('|')
|
101
138
|
|
@@ -114,22 +151,26 @@ module Dwf
|
|
114
151
|
def parse_nodes(id)
|
115
152
|
keys = redis.scan_each(match: "dwf.jobs.#{id}.*")
|
116
153
|
|
117
|
-
keys.map do |key|
|
154
|
+
items = keys.map do |key|
|
118
155
|
redis.hvals(key).map do |json|
|
119
|
-
Dwf::Utils.symbolize_keys JSON.parse(json)
|
156
|
+
node = Dwf::Utils.symbolize_keys JSON.parse(json)
|
157
|
+
Dwf::Item.from_hash(node)
|
120
158
|
end
|
121
159
|
end.flatten
|
160
|
+
workflows = sub_workflows(id)
|
161
|
+
items + workflows
|
122
162
|
end
|
123
163
|
|
124
|
-
def workflow_from_hash(hash,
|
164
|
+
def workflow_from_hash(hash, jobs = [])
|
125
165
|
flow = Module.const_get(hash[:klass]).new(*hash[:arguments])
|
126
166
|
flow.jobs = []
|
167
|
+
flow.outgoing = hash.fetch(:outgoing, [])
|
168
|
+
flow.parent_id = hash[:parent_id]
|
169
|
+
flow.incoming = hash.fetch(:incoming, [])
|
127
170
|
flow.stopped = hash.fetch(:stopped, false)
|
171
|
+
flow.callback_type = hash.fetch(:callback_type, Workflow::BUILD_IN)
|
128
172
|
flow.id = hash[:id]
|
129
|
-
flow.jobs =
|
130
|
-
Dwf::Item.from_hash(node)
|
131
|
-
end
|
132
|
-
|
173
|
+
flow.jobs = jobs
|
133
174
|
flow
|
134
175
|
end
|
135
176
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dwf
|
2
|
+
module Concerns
|
3
|
+
module Checkable
|
4
|
+
def no_dependencies?
|
5
|
+
incoming.empty?
|
6
|
+
end
|
7
|
+
|
8
|
+
def leaf?
|
9
|
+
outgoing.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def ready_to_start?
|
13
|
+
!running? && !enqueued? && !finished? && !failed? && parents_succeeded?
|
14
|
+
end
|
15
|
+
|
16
|
+
def succeeded?
|
17
|
+
finished? && !failed?
|
18
|
+
end
|
19
|
+
|
20
|
+
def running?
|
21
|
+
started? && !finished?
|
22
|
+
end
|
23
|
+
|
24
|
+
def started?
|
25
|
+
!!started_at
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/dwf/errors.rb
CHANGED
data/lib/dwf/item.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'client'
|
4
|
+
require_relative 'concerns/checkable'
|
4
5
|
|
5
6
|
module Dwf
|
6
7
|
class Item
|
8
|
+
include Concerns::Checkable
|
9
|
+
|
7
10
|
attr_reader :workflow_id, :id, :params, :queue, :klass, :started_at,
|
8
|
-
|
9
|
-
|
11
|
+
:enqueued_at, :finished_at, :failed_at, :output_payload
|
12
|
+
attr_writer :payloads
|
13
|
+
attr_accessor :incoming, :outgoing, :callback_type
|
10
14
|
|
11
15
|
def initialize(options = {})
|
12
16
|
assign_attributes(options)
|
@@ -16,9 +20,17 @@ module Dwf
|
|
16
20
|
Module.const_get(hash[:klass]).new(hash)
|
17
21
|
end
|
18
22
|
|
23
|
+
def start_initial!
|
24
|
+
cb_build_in? ? persist_and_perform_async! : start_batch!
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_batch!
|
28
|
+
enqueue_and_persist!
|
29
|
+
Dwf::Callback.new.start(self)
|
30
|
+
end
|
31
|
+
|
19
32
|
def persist_and_perform_async!
|
20
|
-
|
21
|
-
persist!
|
33
|
+
enqueue_and_persist!
|
22
34
|
perform_async
|
23
35
|
end
|
24
36
|
|
@@ -35,7 +47,7 @@ module Dwf
|
|
35
47
|
|
36
48
|
def perform_async
|
37
49
|
Dwf::Worker.set(queue: queue || client.config.namespace)
|
38
|
-
|
50
|
+
.perform_async(workflow_id, name)
|
39
51
|
end
|
40
52
|
|
41
53
|
def name
|
@@ -51,20 +63,11 @@ module Dwf
|
|
51
63
|
end
|
52
64
|
|
53
65
|
def parents_succeeded?
|
54
|
-
incoming.all?
|
55
|
-
client.find_job(workflow_id, name).succeeded?
|
56
|
-
end
|
66
|
+
incoming.all? { |name| client.find_node(name, workflow_id).succeeded? }
|
57
67
|
end
|
58
68
|
|
59
69
|
def payloads
|
60
|
-
|
61
|
-
job = client.find_job(workflow_id, job_name)
|
62
|
-
{
|
63
|
-
id: job.name,
|
64
|
-
class: job.klass.to_s,
|
65
|
-
output: job.output_payload
|
66
|
-
}
|
67
|
-
end
|
70
|
+
@payloads ||= build_payloads
|
68
71
|
end
|
69
72
|
|
70
73
|
def enqueue!
|
@@ -109,22 +112,6 @@ module Dwf
|
|
109
112
|
!failed_at.nil?
|
110
113
|
end
|
111
114
|
|
112
|
-
def succeeded?
|
113
|
-
finished? && !failed?
|
114
|
-
end
|
115
|
-
|
116
|
-
def started?
|
117
|
-
!started_at.nil?
|
118
|
-
end
|
119
|
-
|
120
|
-
def running?
|
121
|
-
started? && !finished?
|
122
|
-
end
|
123
|
-
|
124
|
-
def ready_to_start?
|
125
|
-
!running? && !enqueued? && !finished? && !failed? && parents_succeeded?
|
126
|
-
end
|
127
|
-
|
128
115
|
def current_timestamp
|
129
116
|
Time.now.to_i
|
130
117
|
end
|
@@ -152,7 +139,8 @@ module Dwf
|
|
152
139
|
params: params,
|
153
140
|
workflow_id: workflow_id,
|
154
141
|
callback_type: callback_type,
|
155
|
-
output_payload: output_payload
|
142
|
+
output_payload: output_payload,
|
143
|
+
payloads: @payloads
|
156
144
|
}
|
157
145
|
end
|
158
146
|
|
@@ -166,6 +154,11 @@ module Dwf
|
|
166
154
|
|
167
155
|
private
|
168
156
|
|
157
|
+
def enqueue_and_persist!
|
158
|
+
enqueue!
|
159
|
+
persist!
|
160
|
+
end
|
161
|
+
|
169
162
|
def client
|
170
163
|
@client ||= Dwf::Client.new
|
171
164
|
end
|
@@ -184,6 +177,21 @@ module Dwf
|
|
184
177
|
@started_at = options[:started_at]
|
185
178
|
@callback_type = options[:callback_type]
|
186
179
|
@output_payload = options[:output_payload]
|
180
|
+
@payloads = options[:payloads]
|
181
|
+
end
|
182
|
+
|
183
|
+
def build_payloads
|
184
|
+
data = incoming.map do |job_name|
|
185
|
+
node = client.find_node(job_name, workflow_id)
|
186
|
+
next if node.output_payload.nil?
|
187
|
+
|
188
|
+
{
|
189
|
+
id: node.name,
|
190
|
+
class: node.klass.to_s,
|
191
|
+
output: node.output_payload
|
192
|
+
}
|
193
|
+
end.compact
|
194
|
+
data.empty? ? nil : data
|
187
195
|
end
|
188
196
|
end
|
189
197
|
end
|
data/lib/dwf/utils.rb
CHANGED
data/lib/dwf/version.rb
CHANGED