burstflow 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -3
- data/Gemfile.lock +119 -0
- data/burstflow.gemspec +10 -6
- data/config/database.yml +4 -3
- data/db/migrate/20180101000001_create_workflow.rb +1 -0
- data/db/schema.rb +13 -7
- data/lib/burstflow.rb +11 -0
- data/lib/burstflow/job.rb +102 -0
- data/lib/burstflow/job/callbacks.rb +55 -0
- data/lib/burstflow/job/exception.rb +8 -0
- data/lib/burstflow/job/initialization.rb +35 -0
- data/lib/{burst → burstflow/job}/model.rb +1 -3
- data/lib/burstflow/job/state.rb +125 -0
- data/lib/burstflow/manager.rb +123 -0
- data/lib/burstflow/railtie.rb +6 -0
- data/lib/burstflow/version.rb +3 -0
- data/lib/burstflow/worker.rb +59 -0
- data/lib/burstflow/workflow.rb +207 -0
- data/lib/burstflow/workflow/builder.rb +91 -0
- data/lib/burstflow/workflow/callbacks.rb +66 -0
- data/lib/{burst/workflow_helper.rb → burstflow/workflow/configuration.rb} +8 -39
- data/lib/burstflow/workflow/exception.rb +8 -0
- data/lib/generators/burstflow/install/install_generator.rb +22 -0
- data/lib/generators/burstflow/install/templates/create_workflow.rb +15 -0
- data/spec/builder_spec.rb +63 -0
- data/spec/{burst_spec.rb → burstflow_spec.rb} +1 -1
- data/spec/generators/install_generator_spec.rb +27 -0
- data/spec/job_spec.rb +18 -8
- data/spec/spec_helper.rb +4 -1
- data/spec/support/database_clean.rb +4 -1
- data/spec/workflow_spec.rb +397 -147
- metadata +45 -21
- data/db/migrate/20180101000001_create_workflow.rb +0 -13
- data/db/seeds.rb +0 -1
- data/lib/burst.rb +0 -37
- data/lib/burst/builder.rb +0 -48
- data/lib/burst/configuration.rb +0 -27
- data/lib/burst/job.rb +0 -187
- data/lib/burst/manager.rb +0 -79
- data/lib/burst/worker.rb +0 -42
- data/lib/burst/workflow.rb +0 -148
- data/spec/cases_spec.rb +0 -180
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,8 @@ require 'bundler'
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
Bundler.require(:default)
|
5
5
|
|
6
|
-
require '
|
6
|
+
require 'awesome_print'
|
7
|
+
require 'burstflow'
|
7
8
|
|
8
9
|
|
9
10
|
ActiveJob::Base.queue_adapter = :test
|
@@ -12,6 +13,8 @@ ActiveJob::Base.logger = nil
|
|
12
13
|
$root = File.join(File.dirname(__dir__), 'spec')
|
13
14
|
Dir[File.join($root, 'support', '**', '*.rb')].each {|f| require f }
|
14
15
|
|
16
|
+
#ActiveJob::Base.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
|
17
|
+
ActiveJob::Base.logger = ActiveSupport::Logger.new('/dev/null')
|
15
18
|
|
16
19
|
|
17
20
|
|
data/spec/workflow_spec.rb
CHANGED
@@ -1,185 +1,435 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
describe Burstflow::Workflow do
|
4
|
+
WfJob1 = Class.new(Burstflow::Job)
|
5
|
+
WfJob2 = Class.new(Burstflow::Job)
|
6
|
+
WfJob3 = Class.new(Burstflow::Job)
|
7
|
+
|
8
|
+
class Workflow1 < Burstflow::Workflow
|
9
|
+
$conf1 = configure do |arg1, arg2|
|
10
|
+
$jobid1 = run WfJob1, params: { param1: true, arg: arg1}
|
11
|
+
$jobid2 = run WfJob2, params: { param2: true, arg: arg2}, after: WfJob1
|
12
|
+
$jobid3 = run WfJob3, before: WfJob2, after: $jobid1
|
13
|
+
$jobid4 = run WfJob3, after: $jobid3
|
8
14
|
end
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
class WfJob1 < TestJob
|
13
15
|
end
|
14
16
|
|
15
|
-
class
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
class Workflow2 < Burstflow::Workflow
|
18
|
+
$conf2 = configure do |arg1, arg2|
|
19
|
+
$jobid1 = run WfJob1, params: { param1: true, arg: arg1}
|
20
|
+
$jobid2 = run WfJob2, params: { param2: true, arg: arg2}, after: WfJob1
|
21
|
+
$jobid3 = run WfJob3, before: WfJob2, after: $jobid1
|
22
|
+
$jobid4 = run WfJob3, after: $jobid3
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
26
|
+
describe "initializing" do
|
27
|
+
it "class level configuration" do
|
28
|
+
expect(Burstflow::Workflow.configuration).to eq nil
|
29
|
+
expect(Workflow1.configuration).to eq $conf1
|
30
|
+
expect(Workflow2.configuration).to eq $conf2
|
31
|
+
expect($conf1).not_to eq $conf2
|
32
|
+
end
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
it "build" do
|
35
|
+
Workflow1.build(:arg1, :arg2).save!
|
36
|
+
wf1 = Workflow1.first
|
37
|
+
jobs = wf1.flow['jobs_config']
|
38
|
+
|
39
|
+
expect(jobs.count).to eq 4
|
40
|
+
expect(wf1.initial_jobs.count).to eq 1
|
41
|
+
|
42
|
+
expect(jobs[$jobid1]).to include(:id,
|
43
|
+
klass: WfJob1.to_s,
|
44
|
+
incoming: [],
|
45
|
+
outgoing: [$jobid2, $jobid3],
|
46
|
+
workflow_id: wf1.id,
|
47
|
+
params: {'param1' => true, 'arg' => 'arg1'})
|
48
|
+
|
49
|
+
expect(jobs[$jobid2]).to include(:id,
|
50
|
+
klass: WfJob2.to_s,
|
51
|
+
incoming: [$jobid1, $jobid3],
|
52
|
+
outgoing: [],
|
53
|
+
workflow_id: wf1.id,
|
54
|
+
params: {'param2' => true, 'arg' => 'arg2'})
|
55
|
+
|
56
|
+
expect(jobs[$jobid3]).to include(:id,
|
57
|
+
klass: WfJob3.to_s,
|
58
|
+
incoming: [$jobid1],
|
59
|
+
outgoing: [$jobid2, $jobid4],
|
60
|
+
workflow_id: wf1.id,
|
61
|
+
params: nil)
|
62
|
+
|
63
|
+
expect(jobs[$jobid4]).to include(:id,
|
64
|
+
klass: WfJob3.to_s,
|
65
|
+
incoming: [$jobid3],
|
66
|
+
outgoing: [],
|
67
|
+
workflow_id: wf1.id,
|
68
|
+
params: nil)
|
28
69
|
end
|
29
70
|
|
30
71
|
end
|
31
72
|
|
32
|
-
|
33
|
-
j1, j2, j3 = *jobs
|
73
|
+
describe "executing" do
|
34
74
|
|
35
|
-
|
36
|
-
|
75
|
+
def perform_enqueued_job wf, enqueued_job
|
76
|
+
enqueued_job[:job].new(*enqueued_job[:args]).perform_now
|
37
77
|
|
38
|
-
|
39
|
-
|
40
|
-
|
78
|
+
queue_adapter.performed_jobs << enqueued_job
|
79
|
+
queue_adapter.enqueued_jobs.delete(enqueued_job)
|
80
|
+
|
81
|
+
wf.reload
|
82
|
+
end
|
41
83
|
|
42
|
-
|
43
|
-
expect(j2.outgoing).to include(j3.id)
|
44
|
-
expect(j3.outgoing).to include
|
84
|
+
def perform_enqueued_jobs_async
|
45
85
|
|
46
|
-
|
47
|
-
|
48
|
-
|
86
|
+
jobs = Enumerator.new do |y|
|
87
|
+
while queue_adapter.enqueued_jobs.count > 0
|
88
|
+
y << queue_adapter.enqueued_jobs.shift
|
89
|
+
end
|
90
|
+
end
|
49
91
|
|
50
|
-
|
51
|
-
|
52
|
-
expect(j3.initial?).to eq false
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'model' do
|
56
|
-
it 'default store' do
|
57
|
-
w = Burst::Workflow.new
|
92
|
+
result = yield
|
93
|
+
while queue_adapter.enqueued_jobs.count > 0 do
|
58
94
|
|
59
|
-
|
95
|
+
threads = jobs.map do |job|
|
96
|
+
Thread.new(job) do |job|
|
97
|
+
job[:job].new(*job[:args]).perform_now
|
98
|
+
queue_adapter.performed_jobs << job
|
99
|
+
end
|
100
|
+
end
|
60
101
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
expect(w.running?).to eq false
|
65
|
-
expect(w.status).to eq Burst::Workflow::FINISHED
|
102
|
+
threads.each(&:join)
|
103
|
+
end
|
104
|
+
result
|
66
105
|
end
|
67
106
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
107
|
+
describe "complex" do
|
108
|
+
let(:wf){Workflow1.build(:arg1, :arg2)}
|
109
|
+
|
110
|
+
before do
|
111
|
+
wf.start!
|
112
|
+
end
|
113
|
+
|
114
|
+
it "success story one by one" do
|
115
|
+
expect(Burstflow::Worker).to have_jobs(wf.id, [$jobid1])
|
116
|
+
|
117
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 1
|
118
|
+
expect(queue_adapter.enqueued_jobs.first).to include(args: [wf.id, $jobid1])
|
119
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 1
|
120
|
+
expect(wf.jobs.count(&:started?)).to eq 0
|
121
|
+
expect(wf.jobs.count(&:finished?)).to eq 0
|
122
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
123
|
+
|
124
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
125
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 1
|
126
|
+
expect(queue_adapter.enqueued_jobs.first).to include(args: [wf.id, $jobid3])
|
127
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 2
|
128
|
+
expect(wf.jobs.count(&:started?)).to eq 1
|
129
|
+
expect(wf.jobs.count(&:finished?)).to eq 1
|
130
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
131
|
+
|
132
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
133
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 2
|
134
|
+
expect(queue_adapter.enqueued_jobs.first).to include(args: [wf.id, $jobid2])
|
135
|
+
expect(queue_adapter.enqueued_jobs.last).to include(args: [wf.id, $jobid4])
|
136
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 4
|
137
|
+
expect(wf.jobs.count(&:started?)).to eq 2
|
138
|
+
expect(wf.jobs.count(&:finished?)).to eq 2
|
139
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
140
|
+
|
141
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
142
|
+
expect(queue_adapter.enqueued_jobs.last).to include(args: [wf.id, $jobid4])
|
143
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 1
|
144
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 4
|
145
|
+
expect(wf.jobs.count(&:started?)).to eq 3
|
146
|
+
expect(wf.jobs.count(&:finished?)).to eq 3
|
147
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
148
|
+
|
149
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
150
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 0
|
151
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 4
|
152
|
+
expect(wf.jobs.count(&:started?)).to eq 4
|
153
|
+
expect(wf.jobs.count(&:finished?)).to eq 4
|
154
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
it "success story all at once sync" do
|
159
|
+
perform_enqueued_jobs do
|
160
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
161
|
+
end
|
162
|
+
|
163
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 0
|
164
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 4
|
165
|
+
expect(wf.jobs.count(&:started?)).to eq 4
|
166
|
+
expect(wf.jobs.count(&:finished?)).to eq 4
|
167
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
168
|
+
end
|
169
|
+
|
170
|
+
it "success story all at once async", threads: true do
|
171
|
+
perform_enqueued_jobs_async do
|
172
|
+
perform_enqueued_job(wf, queue_adapter.enqueued_jobs.first)
|
173
|
+
end
|
174
|
+
|
175
|
+
wf.reload
|
176
|
+
expect(queue_adapter.enqueued_jobs.count).to eq 0
|
177
|
+
expect(wf.jobs.count(&:enqueued?)).to eq 4
|
178
|
+
expect(wf.jobs.count(&:started?)).to eq 4
|
179
|
+
expect(wf.jobs.count(&:finished?)).to eq 4
|
180
|
+
expect(wf.jobs.count(&:ready_to_start?)).to eq 0
|
181
|
+
end
|
74
182
|
end
|
75
183
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
184
|
+
describe "concurrency" do
|
185
|
+
class MapJob1 < Burstflow::Job
|
186
|
+
def perform
|
187
|
+
set_output(params['i'])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class ReduceJob1 < Burstflow::Job
|
192
|
+
def perform
|
193
|
+
set_output(payloads.map{|p| p[:value]}.sum)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class ConcWorkflow < Burstflow::Workflow
|
198
|
+
configure do |size|
|
199
|
+
size.to_i.times.to_a.shuffle.each do |i|
|
200
|
+
run MapJob1, params: {i: i}, before: ReduceJob1
|
201
|
+
end
|
202
|
+
|
203
|
+
$jobid = run ReduceJob1
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
let(:count){50}
|
208
|
+
let(:expected_result){count.times.sum}
|
209
|
+
|
210
|
+
it "sync" do
|
211
|
+
wf = perform_enqueued_jobs do
|
212
|
+
ConcWorkflow.build(count).start!
|
213
|
+
end.reload
|
214
|
+
|
215
|
+
expect(wf.job($jobid).output).to eq expected_result
|
216
|
+
end
|
217
|
+
|
218
|
+
it "threaded", threads: true do
|
219
|
+
wf = perform_enqueued_jobs_async do
|
220
|
+
ConcWorkflow.build(count).start!
|
221
|
+
end.reload
|
222
|
+
|
223
|
+
expect(wf.job($jobid).output).to eq expected_result
|
224
|
+
end
|
83
225
|
end
|
84
226
|
|
85
|
-
|
86
|
-
|
87
|
-
|
227
|
+
describe "simple" do
|
228
|
+
WfSimpleJob = Class.new(Burstflow::Job)
|
229
|
+
WfFailureJob = Class.new(Burstflow::Job) do
|
230
|
+
def perform
|
231
|
+
raise "ex"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
WfSuspendJob = Class.new(Burstflow::Job) do
|
236
|
+
def perform
|
237
|
+
return Burstflow::Job::SUSPEND
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "parallel failure" do
|
242
|
+
class Workflow3 < Burstflow::Workflow
|
243
|
+
configure do |arg1, arg2|
|
244
|
+
$jobid1 = run WfSimpleJob
|
245
|
+
$jobid2 = run WfFailureJob
|
246
|
+
$jobid3 = run WfSimpleJob, after: $jobid2
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
it "run" do
|
251
|
+
wf = perform_enqueued_jobs do
|
252
|
+
Workflow3.build.start!
|
253
|
+
end.reload
|
254
|
+
|
255
|
+
expect(wf.status).to eq Burstflow::Workflow::FAILED
|
256
|
+
expect(wf.failures.first).to include(:created_at, job: $jobid2)
|
257
|
+
|
258
|
+
expect(wf.job($jobid1).succeeded?).to eq true
|
259
|
+
|
260
|
+
expect(wf.job($jobid2).succeeded?).to eq false
|
261
|
+
expect(wf.job($jobid2).failed?).to eq true
|
262
|
+
expect(wf.job($jobid2).failure).to include(klass: 'RuntimeError', message: 'ex')
|
263
|
+
|
264
|
+
expect(wf.job($jobid3).enqueued?).to eq false
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "parallel suspend" do
|
269
|
+
class Workflow4 < Burstflow::Workflow
|
270
|
+
configure do |arg1, arg2|
|
271
|
+
$jobid1 = run WfSimpleJob
|
272
|
+
$jobid2 = run WfSuspendJob
|
273
|
+
$jobid3 = run WfSimpleJob, after: $jobid2
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
it "run" do
|
278
|
+
wf = perform_enqueued_jobs do
|
279
|
+
Workflow4.build.start!
|
280
|
+
end.reload
|
281
|
+
|
282
|
+
expect(wf.status).to eq Burstflow::Workflow::SUSPENDED
|
283
|
+
|
284
|
+
expect(wf.job($jobid1).succeeded?).to eq true
|
285
|
+
expect(wf.job($jobid2).suspended?).to eq true
|
286
|
+
expect(wf.job($jobid3).enqueued?).to eq false
|
287
|
+
|
288
|
+
wf = perform_enqueued_jobs do
|
289
|
+
wf.resume!($jobid2, "gogogo")
|
290
|
+
end.reload
|
291
|
+
|
292
|
+
expect(wf.status).to eq Burstflow::Workflow::FINISHED
|
293
|
+
|
294
|
+
expect(wf.job($jobid1).succeeded?).to eq true
|
295
|
+
expect(wf.job($jobid2).succeeded?).to eq true
|
296
|
+
expect(wf.job($jobid3).succeeded?).to eq true
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
describe "dynamic job creation" do
|
301
|
+
let(:count) {10}
|
302
|
+
let(:expected_result) {(count + 1).times.sum}
|
303
|
+
|
304
|
+
WfDynamicJob = Class.new(Burstflow::Job) do
|
305
|
+
def perform
|
306
|
+
if params['i'] > 0
|
307
|
+
configure(self.id, params) do |id, params|
|
308
|
+
$lasjobid = run WfDynamicJob, params: {i: params['i'] - 1}, after: id
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
output = if payload = payloads.first
|
313
|
+
payload[:value] + params['i']
|
314
|
+
else
|
315
|
+
params['i']
|
316
|
+
end
|
317
|
+
|
318
|
+
set_output(output)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class WorkflowDynamic < Burstflow::Workflow
|
323
|
+
configure do |count|
|
324
|
+
run WfDynamicJob, params: {i: count}
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
it "run" do
|
329
|
+
wf = WorkflowDynamic.build(count)
|
330
|
+
wf.save!
|
331
|
+
|
332
|
+
expect(wf.jobs.count).to eq 1
|
333
|
+
|
334
|
+
wf = perform_enqueued_jobs do
|
335
|
+
WorkflowDynamic.build(count).start!
|
336
|
+
end.reload
|
337
|
+
|
338
|
+
expect(wf.jobs.count).to eq 11
|
339
|
+
expect(wf.job($lasjobid).output).to eq expected_result
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "callbacks" do
|
345
|
+
|
346
|
+
WfCallJob = Class.new(Burstflow::Job) do
|
347
|
+
before_enqueue :be
|
348
|
+
before_perform :bp
|
349
|
+
before_suspend :bs
|
350
|
+
before_resume :br
|
351
|
+
before_failure :bf
|
352
|
+
|
353
|
+
def be;$be = true;end
|
354
|
+
def bp;$bp = true;end
|
355
|
+
def bs;$bs = true;end
|
356
|
+
def br;$br = true;end
|
357
|
+
def bf;$bf = true;end
|
358
|
+
|
359
|
+
def perform
|
360
|
+
suspend()
|
361
|
+
end
|
362
|
+
|
363
|
+
def resume data
|
364
|
+
raise "ex"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
class WorkflowCall < Burstflow::Workflow
|
369
|
+
before_suspend :wbs
|
370
|
+
before_resume :wbr
|
371
|
+
before_failure :wbf
|
372
|
+
|
373
|
+
def wbs;$wbs = true;end
|
374
|
+
def wbr;$wbr = true;end
|
375
|
+
def wbf;$wbf = true;end
|
376
|
+
|
377
|
+
configure do
|
378
|
+
$jobid1 = run WfCallJob
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
it "run" do
|
383
|
+
expect([$be, $bp, $bs, $br, $bf].any?).to eq false
|
384
|
+
expect([$wbs, $wbr, $wbf].any?).to eq false
|
385
|
+
|
386
|
+
wf = perform_enqueued_jobs do
|
387
|
+
WorkflowCall.build.start!
|
388
|
+
end.reload
|
389
|
+
|
390
|
+
wf = perform_enqueued_jobs do
|
391
|
+
wf.resume!($jobid1, '123123123')
|
392
|
+
end.reload
|
393
|
+
|
394
|
+
expect(wf.status).to eq Burstflow::Workflow::FAILED
|
395
|
+
expect(wf.failures.first).to include(:created_at, job: $jobid1)
|
396
|
+
|
397
|
+
expect(wf.job($jobid1).succeeded?).to eq false
|
398
|
+
expect(wf.job($jobid1).failed?).to eq true
|
399
|
+
expect(wf.job($jobid1).failure).to include(klass: 'RuntimeError', message: 'ex')
|
400
|
+
|
401
|
+
expect([$be, $bp, $bs, $br, $bf].all?).to eq true
|
402
|
+
expect([$wbs, $wbr, $wbf].all?).to eq true
|
403
|
+
end
|
404
|
+
end
|
88
405
|
|
89
|
-
jobs = w.jobs
|
90
|
-
expect_jobs(*jobs.values.map{|json| Burst::Job.new(w, json) })
|
91
406
|
|
92
|
-
w2 = Burst::Workflow.find(w.id)
|
93
|
-
expect(w2.attributes).to include(w.attributes)
|
94
407
|
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def expect_wf(w)
|
98
|
-
j1 = w.find_job('job1')
|
99
|
-
j2 = w.find_job('job2')
|
100
|
-
j3 = w.find_job(WfJob3)
|
101
|
-
|
102
|
-
expect(j1.finished?).to eq false
|
103
|
-
expect(j2.finished?).to eq false
|
104
408
|
|
105
|
-
expect(j1.klass).to eq 'WfJob1'
|
106
|
-
expect(j2.klass).to eq 'WfJob2'
|
107
|
-
expect(j3.klass).to eq 'WfJob3'
|
108
|
-
|
109
|
-
expect(j1.outgoing).to include(j2.id, j3.id)
|
110
|
-
expect(j2.outgoing).to include(j3.id)
|
111
|
-
expect(j3.outgoing).to include
|
112
|
-
|
113
|
-
expect(j1.incoming).to include
|
114
|
-
expect(j2.incoming).to include(j1.id)
|
115
|
-
expect(j3.incoming).to include(j1.id, j2.id)
|
116
|
-
|
117
|
-
expect(j1.initial?).to eq true
|
118
|
-
expect(j2.initial?).to eq false
|
119
|
-
expect(j3.initial?).to eq false
|
120
|
-
|
121
|
-
expect(w.initial_jobs).to include(j1)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'check builder' do
|
125
|
-
w = W1.build
|
126
|
-
expect_wf(w)
|
127
|
-
|
128
|
-
expect(w.status)
|
129
409
|
end
|
410
|
+
|
411
|
+
context 'model' do
|
412
|
+
it 'default store' do
|
413
|
+
w = Burstflow::Workflow.new
|
130
414
|
|
131
|
-
|
132
|
-
w = W1.build
|
133
|
-
w.save!
|
134
|
-
|
135
|
-
w2 = W1.find(w.id)
|
136
|
-
expect_wf(w2)
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'start without perform' do
|
140
|
-
w = W1.build
|
141
|
-
w.save!
|
142
|
-
|
143
|
-
expect(w.started?).to eq false
|
144
|
-
expect(w.failed?).to eq false
|
145
|
-
expect(w.finished?).to eq false
|
146
|
-
expect(w.running?).to eq false
|
147
|
-
expect(w.status).to eq Burst::Workflow::INITIAL
|
148
|
-
|
149
|
-
w.start!
|
150
|
-
|
151
|
-
expect(Burst::Worker).to have_jobs(w.id, ['job1'])
|
152
|
-
expect(Burst::Worker).not_to have_jobs(w.id, ['job2'])
|
153
|
-
|
154
|
-
w = W1.find(w.id)
|
415
|
+
expect(w.attributes).to include(:id, jobs_config: {}, type: Burstflow::Workflow.to_s)
|
155
416
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
it 'start with perform' do
|
164
|
-
w = W1.build
|
165
|
-
w.save!
|
417
|
+
expect(w.initial?).to eq true
|
418
|
+
expect(w.failed?).to eq false
|
419
|
+
expect(w.finished?).to eq false
|
420
|
+
expect(w.running?).to eq false
|
421
|
+
expect(w.suspended?).to eq false
|
422
|
+
expect(w.status).to eq Burstflow::Workflow::INITIAL
|
423
|
+
end
|
166
424
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
expect(w.running?).to eq false
|
171
|
-
expect(w.status).to eq Burst::Workflow::INITIAL
|
425
|
+
it 'store persistance' do
|
426
|
+
w = Burstflow::Workflow.new
|
427
|
+
w.save!
|
172
428
|
|
173
|
-
|
174
|
-
w.
|
429
|
+
w2 = Burstflow::Workflow.find(w.id)
|
430
|
+
expect(w2.attributes).to include(w.attributes)
|
175
431
|
end
|
176
432
|
|
177
|
-
w = W1.find(w.id)
|
178
|
-
|
179
|
-
expect(w.started?).to eq true
|
180
|
-
expect(w.failed?).to eq false
|
181
|
-
expect(w.finished?).to eq true
|
182
|
-
expect(w.running?).to eq false
|
183
|
-
expect(w.status).to eq Burst::Workflow::FINISHED
|
184
433
|
end
|
434
|
+
|
185
435
|
end
|