dwf 0.1.7 → 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 +137 -0
- data/README.md +155 -33
- data/dwf.gemspec +2 -1
- data/lib/dwf/callback.rb +13 -10
- data/lib/dwf/client.rb +76 -1
- data/lib/dwf/concerns/checkable.rb +29 -0
- data/lib/dwf/configuration.rb +1 -1
- data/lib/dwf/errors.rb +5 -0
- data/lib/dwf/item.rb +71 -37
- data/lib/dwf/utils.rb +6 -0
- data/lib/dwf/version.rb +1 -1
- data/lib/dwf/worker.rb +1 -1
- data/lib/dwf/workflow.rb +145 -34
- data/spec/dwf/client_spec.rb +100 -3
- data/spec/dwf/item_spec.rb +81 -6
- data/spec/dwf/utils_spec.rb +9 -0
- data/spec/dwf/worker_spec.rb +32 -0
- data/spec/dwf/workflow_spec.rb +349 -0
- data/spec/spec_helper.rb +3 -0
- metadata +32 -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,142 @@
|
|
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
|
+
|
70
|
+
## 0.1.10
|
71
|
+
### Added
|
72
|
+
- Allow to use argument within workflow and update the defining callback way
|
73
|
+
```
|
74
|
+
class TestWf < Dwf::Workflow
|
75
|
+
def configure(arguments)
|
76
|
+
run A
|
77
|
+
run B, after: A, params: argument
|
78
|
+
run C, after: A, params: argument
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
wf = TestWf.create(arguments)
|
83
|
+
wf.callback_type = Dwf::Workflow::SK_BATCH
|
84
|
+
|
85
|
+
```
|
86
|
+
- Support `find` workflow and `reload` workflow
|
87
|
+
```
|
88
|
+
wf = TestWf.create
|
89
|
+
Dwf::Workflow.find(wf.id)
|
90
|
+
wf.reload
|
91
|
+
```
|
92
|
+
|
93
|
+
## 0.1.9
|
94
|
+
### Added
|
95
|
+
### Fixed
|
96
|
+
- fix incorrect argument at configuration
|
97
|
+
|
98
|
+
## 0.1.8
|
99
|
+
### Added
|
100
|
+
- add pinlining feature
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
class SendOutput < Dwf::Item
|
104
|
+
def perform
|
105
|
+
output('it works')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
```
|
110
|
+
|
111
|
+
`output` method used to output data from the job to add outgoing jobs
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
class ReceiveOutput < Dwf::Item
|
115
|
+
def perform
|
116
|
+
message = payloads.first[:output] # it works
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
`payloads` is an array that containing outputs from incoming jobs
|
122
|
+
|
123
|
+
```
|
124
|
+
[
|
125
|
+
{
|
126
|
+
id: "SendOutput|1849a3f9-5fce-401e-a73a-91fc1048356",
|
127
|
+
class: "SendOutput",
|
128
|
+
output: 'it works'
|
129
|
+
}
|
130
|
+
]
|
131
|
+
```
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
Dwf.config do |config|
|
135
|
+
config.opts = { url 'redis://127.0.0.1:6379' }
|
136
|
+
config.namespace = 'dwf'
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
3
140
|
## 0.1.7
|
4
141
|
### Added
|
5
142
|
- Allow to config redis and queue
|
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,20 +51,23 @@ 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
|
44
|
-
wf = TestWf.create
|
69
|
+
wf = TestWf.create
|
70
|
+
wf.callback_type = Dwf::Workflow::SK_BATCH
|
45
71
|
wf.start!
|
46
72
|
```
|
47
73
|
|
@@ -54,35 +80,128 @@ By default `dwf` will use `Dwf::Workflow::BUILD_IN` callback.
|
|
54
80
|
|
55
81
|
### Output
|
56
82
|
```
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
E say hello
|
68
|
-
E Finished
|
69
|
-
D Working
|
70
|
-
D say hello
|
71
|
-
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
|
72
93
|
```
|
73
94
|
|
74
95
|
# Config redis and default queue
|
96
|
+
`dwf` uses redis as the key value stograge through [redis-rb](https://github.com/redis/redis-rb), So you can pass redis configuration by `redis_opts`
|
75
97
|
```ruby
|
76
98
|
Dwf.config do |config|
|
77
99
|
SENTINELS = [
|
78
100
|
{ host: "127.0.0.1", port: 26380 },
|
79
101
|
{ host: "127.0.0.1", port: 26381 }
|
80
102
|
]
|
81
|
-
config.
|
103
|
+
config.redis_opts = { host: 'mymaster', sentinels: SENTINELS, role: :master }
|
82
104
|
config.namespace = 'dwf'
|
83
105
|
end
|
84
106
|
```
|
107
|
+
# Advanced features
|
108
|
+
## Pipelining
|
109
|
+
You can pass jobs result to next nodes
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
class SendOutput < Dwf::Item
|
113
|
+
def perform
|
114
|
+
output('it works')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
```
|
119
|
+
|
120
|
+
`output` method used to output data from the job to add outgoing jobs
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
class ReceiveOutput < Dwf::Item
|
124
|
+
def perform
|
125
|
+
message = payloads.first[:output] # it works
|
126
|
+
end
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
`payloads` is an array that containing outputs from incoming jobs
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
[
|
134
|
+
{
|
135
|
+
id: "SendOutput|1849a3f9-5fce-401e-a73a-91fc1048356",
|
136
|
+
class: "SendOutput",
|
137
|
+
output: 'it works'
|
138
|
+
}
|
139
|
+
]
|
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
|
+
```
|
85
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
|
+
```
|
86
205
|
|
87
206
|
# Todo
|
88
207
|
- [x] Make it work
|
@@ -90,9 +209,12 @@ end
|
|
90
209
|
- [x] Support with build-in callback
|
91
210
|
- [x] Add github workflow
|
92
211
|
- [x] Redis configurable
|
93
|
-
- [
|
94
|
-
- [
|
212
|
+
- [x] Pipelining
|
213
|
+
- [X] Test
|
214
|
+
- [ ] WIP - subworkflow
|
95
215
|
- [ ] Support [Resque](https://github.com/resque/resque)
|
216
|
+
- [ ] Key value store plugable
|
217
|
+
- [ ] research https://github.com/moneta-rb/moneta
|
96
218
|
|
97
219
|
# References
|
98
220
|
- https://github.com/chaps-io/gush
|
data/dwf.gemspec
CHANGED
@@ -26,8 +26,9 @@ Gem::Specification.new do |spec|
|
|
26
26
|
# guide at: https://bundler.io/guides/creating_gem.html
|
27
27
|
|
28
28
|
spec.add_development_dependency 'byebug', '~> 11.1.3'
|
29
|
+
spec.add_development_dependency 'mock_redis', '~> 0.27.2'
|
29
30
|
spec.add_dependency 'redis', '~> 4.2.0'
|
30
31
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
31
|
-
spec.add_development_dependency 'mock_redis', '~> 0.27.2'
|
32
32
|
spec.add_dependency 'sidekiq', '~> 6.2.0'
|
33
|
+
spec.add_development_dependency 'simplecov'
|
33
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
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
|
1
3
|
module Dwf
|
2
4
|
class Client
|
3
5
|
attr_reader :config
|
@@ -20,6 +22,43 @@ module Dwf
|
|
20
22
|
Dwf::Item.from_hash(Dwf::Utils.symbolize_keys(data))
|
21
23
|
end
|
22
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
|
+
|
38
|
+
def find_workflow(id)
|
39
|
+
key = redis.keys("dwf.workflows.#{id}*").first
|
40
|
+
data = redis.get(key)
|
41
|
+
raise WorkflowNotFound, "Workflow with given id doesn't exist" if data.nil?
|
42
|
+
|
43
|
+
hash = JSON.parse(data)
|
44
|
+
hash = Dwf::Utils.symbolize_keys(hash)
|
45
|
+
nodes = parse_nodes(id)
|
46
|
+
workflow_from_hash(hash, nodes)
|
47
|
+
end
|
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
|
+
|
23
62
|
def persist_job(job)
|
24
63
|
redis.hset("dwf.jobs.#{job.workflow_id}.#{job.klass}", job.id, job.as_json)
|
25
64
|
end
|
@@ -39,7 +78,10 @@ module Dwf
|
|
39
78
|
end
|
40
79
|
|
41
80
|
def persist_workflow(workflow)
|
42
|
-
|
81
|
+
key = [
|
82
|
+
'dwf', 'workflows', workflow.id, workflow.class.name, workflow.parent_id
|
83
|
+
].compact.join('.')
|
84
|
+
redis.set(key, workflow.as_json)
|
43
85
|
end
|
44
86
|
|
45
87
|
def build_job_id(workflow_id, job_klass)
|
@@ -84,6 +126,13 @@ module Dwf
|
|
84
126
|
|
85
127
|
private
|
86
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
|
+
|
87
136
|
def find_job_by_klass_and_id(workflow_id, job_name)
|
88
137
|
job_klass, job_id = job_name.split('|')
|
89
138
|
|
@@ -99,6 +148,32 @@ module Dwf
|
|
99
148
|
job
|
100
149
|
end
|
101
150
|
|
151
|
+
def parse_nodes(id)
|
152
|
+
keys = redis.scan_each(match: "dwf.jobs.#{id}.*")
|
153
|
+
|
154
|
+
items = keys.map do |key|
|
155
|
+
redis.hvals(key).map do |json|
|
156
|
+
node = Dwf::Utils.symbolize_keys JSON.parse(json)
|
157
|
+
Dwf::Item.from_hash(node)
|
158
|
+
end
|
159
|
+
end.flatten
|
160
|
+
workflows = sub_workflows(id)
|
161
|
+
items + workflows
|
162
|
+
end
|
163
|
+
|
164
|
+
def workflow_from_hash(hash, jobs = [])
|
165
|
+
flow = Module.const_get(hash[:klass]).new(*hash[:arguments])
|
166
|
+
flow.jobs = []
|
167
|
+
flow.outgoing = hash.fetch(:outgoing, [])
|
168
|
+
flow.parent_id = hash[:parent_id]
|
169
|
+
flow.incoming = hash.fetch(:incoming, [])
|
170
|
+
flow.stopped = hash.fetch(:stopped, false)
|
171
|
+
flow.callback_type = hash.fetch(:callback_type, Workflow::BUILD_IN)
|
172
|
+
flow.id = hash[:id]
|
173
|
+
flow.jobs = jobs
|
174
|
+
flow
|
175
|
+
end
|
176
|
+
|
102
177
|
def redis
|
103
178
|
@redis ||= Redis.new(config.redis_opts)
|
104
179
|
end
|
@@ -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/configuration.rb
CHANGED