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