burstflow 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +1 -3
  3. data/Gemfile.lock +119 -0
  4. data/burstflow.gemspec +10 -6
  5. data/config/database.yml +4 -3
  6. data/db/migrate/20180101000001_create_workflow.rb +1 -0
  7. data/db/schema.rb +13 -7
  8. data/lib/burstflow.rb +11 -0
  9. data/lib/burstflow/job.rb +102 -0
  10. data/lib/burstflow/job/callbacks.rb +55 -0
  11. data/lib/burstflow/job/exception.rb +8 -0
  12. data/lib/burstflow/job/initialization.rb +35 -0
  13. data/lib/{burst → burstflow/job}/model.rb +1 -3
  14. data/lib/burstflow/job/state.rb +125 -0
  15. data/lib/burstflow/manager.rb +123 -0
  16. data/lib/burstflow/railtie.rb +6 -0
  17. data/lib/burstflow/version.rb +3 -0
  18. data/lib/burstflow/worker.rb +59 -0
  19. data/lib/burstflow/workflow.rb +207 -0
  20. data/lib/burstflow/workflow/builder.rb +91 -0
  21. data/lib/burstflow/workflow/callbacks.rb +66 -0
  22. data/lib/{burst/workflow_helper.rb → burstflow/workflow/configuration.rb} +8 -39
  23. data/lib/burstflow/workflow/exception.rb +8 -0
  24. data/lib/generators/burstflow/install/install_generator.rb +22 -0
  25. data/lib/generators/burstflow/install/templates/create_workflow.rb +15 -0
  26. data/spec/builder_spec.rb +63 -0
  27. data/spec/{burst_spec.rb → burstflow_spec.rb} +1 -1
  28. data/spec/generators/install_generator_spec.rb +27 -0
  29. data/spec/job_spec.rb +18 -8
  30. data/spec/spec_helper.rb +4 -1
  31. data/spec/support/database_clean.rb +4 -1
  32. data/spec/workflow_spec.rb +397 -147
  33. metadata +45 -21
  34. data/db/migrate/20180101000001_create_workflow.rb +0 -13
  35. data/db/seeds.rb +0 -1
  36. data/lib/burst.rb +0 -37
  37. data/lib/burst/builder.rb +0 -48
  38. data/lib/burst/configuration.rb +0 -27
  39. data/lib/burst/job.rb +0 -187
  40. data/lib/burst/manager.rb +0 -79
  41. data/lib/burst/worker.rb +0 -42
  42. data/lib/burst/workflow.rb +0 -148
  43. data/spec/cases_spec.rb +0 -180
@@ -3,7 +3,8 @@ require 'bundler'
3
3
  require 'bundler/setup'
4
4
  Bundler.require(:default)
5
5
 
6
- require 'burst'
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
 
@@ -7,7 +7,10 @@ RSpec.configure do |config|
7
7
 
8
8
  config.before(:each) do
9
9
  DatabaseCleaner.strategy = :transaction
10
- DatabaseCleaner.start
10
+ end
11
+
12
+ config.before(:each, threads: true) do
13
+ DatabaseCleaner.strategy = :truncation
11
14
  end
12
15
 
13
16
  config.after(:each) do
@@ -1,185 +1,435 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Burst::Workflow do
4
- class TestJob < Burst::Job
5
-
6
- def perform
7
- # puts "#{self.class} perform"
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 WfJob2 < TestJob
16
- end
17
-
18
- class WfJob3 < TestJob
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
- class W1 < Burst::Workflow
23
-
24
- configure do |*_args|
25
- id1 = run WfJob1, id: 'job1'
26
- run WfJob2, id: 'job2', after: id1
27
- run WfJob3, after: [WfJob1, 'job2']
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
- def expect_jobs(*jobs)
33
- j1, j2, j3 = *jobs
73
+ describe "executing" do
34
74
 
35
- expect(j1.finished?).to eq false
36
- expect(j2.finished?).to eq false
75
+ def perform_enqueued_job wf, enqueued_job
76
+ enqueued_job[:job].new(*enqueued_job[:args]).perform_now
37
77
 
38
- expect(j1.klass).to eq 'WfJob1'
39
- expect(j2.klass).to eq 'WfJob2'
40
- expect(j3.klass).to eq 'WfJob3'
78
+ queue_adapter.performed_jobs << enqueued_job
79
+ queue_adapter.enqueued_jobs.delete(enqueued_job)
80
+
81
+ wf.reload
82
+ end
41
83
 
42
- expect(j1.outgoing).to include(j2.id, j3.id)
43
- expect(j2.outgoing).to include(j3.id)
44
- expect(j3.outgoing).to include
84
+ def perform_enqueued_jobs_async
45
85
 
46
- expect(j1.incoming).to include
47
- expect(j2.incoming).to include(j1.id)
48
- expect(j3.incoming).to include(j1.id, j2.id)
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
- expect(j1.initial?).to eq true
51
- expect(j2.initial?).to eq false
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
- expect(w.attributes).to include(:id, jobs: {}, klass: Burst::Workflow.to_s)
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
- expect(w.started?).to eq false
62
- expect(w.failed?).to eq false
63
- expect(w.finished?).to eq true
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
- it 'store persistance' do
69
- w = Burst::Workflow.new
70
- w.save!
71
-
72
- w2 = Burst::Workflow.find(w.id)
73
- expect(w2.attributes).to include(w.attributes)
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
- it 'builded store' do
77
- w = W1.build
78
-
79
- jobs = w.jobs
80
- expect_jobs(*jobs.values.map{|json| Burst::Job.new(w, json) })
81
-
82
- expect(w.attributes).to include(:id, jobs: jobs, klass: W1.to_s)
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
- it 'builded persistance' do
86
- w = W1.build
87
- w.save!
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
- it 'check persistance' do
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
- expect(w.started?).to eq false
157
- expect(w.failed?).to eq false
158
- expect(w.finished?).to eq false
159
- expect(w.running?).to eq false
160
- expect(w.status).to eq Burst::Workflow::INITIAL
161
- end
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
- expect(w.started?).to eq false
168
- expect(w.failed?).to eq false
169
- expect(w.finished?).to eq false
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
- perform_enqueued_jobs do
174
- w.start!
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