taskinator 0.2.0 → 0.3.0

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +17 -2
  4. data/Gemfile.lock +57 -18
  5. data/README.md +20 -16
  6. data/lib/taskinator/definition.rb +2 -2
  7. data/lib/taskinator/instrumentation.rb +77 -0
  8. data/lib/taskinator/persistence.rb +72 -61
  9. data/lib/taskinator/process.rb +118 -99
  10. data/lib/taskinator/queues/delayed_job.rb +0 -14
  11. data/lib/taskinator/queues/resque.rb +0 -18
  12. data/lib/taskinator/queues/sidekiq.rb +0 -14
  13. data/lib/taskinator/queues.rb +0 -5
  14. data/lib/taskinator/task.rb +113 -70
  15. data/lib/taskinator/version.rb +1 -1
  16. data/lib/taskinator/visitor.rb +6 -0
  17. data/lib/taskinator/workflow.rb +36 -0
  18. data/lib/taskinator.rb +3 -2
  19. data/spec/examples/process_examples.rb +6 -9
  20. data/spec/examples/queue_adapter_examples.rb +2 -12
  21. data/spec/examples/task_examples.rb +5 -8
  22. data/spec/support/process_methods.rb +25 -0
  23. data/spec/support/task_methods.rb +13 -0
  24. data/spec/support/test_flows.rb +1 -3
  25. data/spec/support/test_instrumenter.rb +39 -0
  26. data/spec/support/test_queue.rb +0 -12
  27. data/spec/taskinator/definition_spec.rb +3 -5
  28. data/spec/taskinator/instrumentation_spec.rb +98 -0
  29. data/spec/taskinator/persistence_spec.rb +3 -41
  30. data/spec/taskinator/process_spec.rb +36 -34
  31. data/spec/taskinator/queues/delayed_job_spec.rb +0 -41
  32. data/spec/taskinator/queues/resque_spec.rb +0 -51
  33. data/spec/taskinator/queues/sidekiq_spec.rb +0 -50
  34. data/spec/taskinator/queues_spec.rb +1 -1
  35. data/spec/taskinator/task_spec.rb +96 -64
  36. data/spec/taskinator/test_flows_spec.rb +266 -1
  37. data/taskinator.gemspec +0 -21
  38. metadata +12 -173
  39. data/lib/taskinator/job_worker.rb +0 -17
  40. data/spec/taskinator/job_worker_spec.rb +0 -62
@@ -4,11 +4,19 @@ describe Taskinator::Task do
4
4
 
5
5
  let(:definition) { TestDefinition }
6
6
 
7
- describe "Base" do
7
+ let(:process) do
8
+ Class.new(Taskinator::Process) do
9
+ include ProcessMethods
10
+ end.new(definition)
11
+ end
8
12
 
9
- let(:process) { Class.new(Taskinator::Process).new(definition) }
13
+ describe "Base" do
10
14
 
11
- subject { Class.new(Taskinator::Task).new(process) }
15
+ subject do
16
+ Class.new(Taskinator::Task) do
17
+ include TaskMethods
18
+ end.new(process)
19
+ end
12
20
 
13
21
  describe "#initialize" do
14
22
  it { expect(subject.process).to_not be_nil }
@@ -45,9 +53,9 @@ describe Taskinator::Task do
45
53
  end
46
54
 
47
55
  describe "#current_state" do
48
- it { expect(subject).to be_a(::Workflow) }
56
+ it { expect(subject).to be_a(Taskinator::Workflow) }
49
57
  it { expect(subject.current_state).to_not be_nil }
50
- it { expect(subject.current_state.name).to eq(:initial) }
58
+ it { expect(subject.current_state).to eq(:initial) }
51
59
  end
52
60
 
53
61
  describe "workflow" do
@@ -59,7 +67,7 @@ describe Taskinator::Task do
59
67
  }
60
68
  it {
61
69
  subject.enqueue!
62
- expect(subject.current_state.name).to eq(:enqueued)
70
+ expect(subject.current_state).to eq(:enqueued)
63
71
  }
64
72
  end
65
73
 
@@ -71,7 +79,7 @@ describe Taskinator::Task do
71
79
  }
72
80
  it {
73
81
  subject.start!
74
- expect(subject.current_state.name).to eq(:processing)
82
+ expect(subject.current_state).to eq(:processing)
75
83
  }
76
84
  end
77
85
 
@@ -81,7 +89,7 @@ describe Taskinator::Task do
81
89
  expect(subject).to receive(:complete)
82
90
  subject.start!
83
91
  subject.complete!
84
- expect(subject.current_state.name).to eq(:completed)
92
+ expect(subject.current_state).to eq(:completed)
85
93
  }
86
94
  end
87
95
 
@@ -96,8 +104,8 @@ describe Taskinator::Task do
96
104
  }
97
105
  it {
98
106
  subject.start!
99
- subject.fail!
100
- expect(subject.current_state.name).to eq(:failed)
107
+ subject.fail!(StandardError.new)
108
+ expect(subject.current_state).to eq(:failed)
101
109
  }
102
110
  end
103
111
 
@@ -106,7 +114,7 @@ describe Taskinator::Task do
106
114
  it {
107
115
  process.start!
108
116
  process.pause!
109
- expect(subject.paused?).to be
117
+ expect(subject.paused?).to eq(true)
110
118
  }
111
119
  end
112
120
 
@@ -139,6 +147,8 @@ describe Taskinator::Task do
139
147
  expect(visitor).to receive(:visit_task_reference).with(:next)
140
148
  expect(visitor).to receive(:visit_args).with(:options)
141
149
  expect(visitor).to receive(:visit_attribute).with(:queue)
150
+ expect(visitor).to receive(:visit_attribute_time).with(:created_at)
151
+ expect(visitor).to receive(:visit_attribute_time).with(:updated_at)
142
152
 
143
153
  subject.accept(visitor)
144
154
  }
@@ -152,14 +162,11 @@ describe Taskinator::Task do
152
162
  end
153
163
 
154
164
  describe Taskinator::Task::Step do
155
- it_should_behave_like "a task", Taskinator::Task::Step do
156
- let(:process) { Class.new(Taskinator::Process).new(definition) }
157
- let(:task) { Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}) }
158
- end
159
165
 
160
- let(:process) { Class.new(Taskinator::Process).new(definition) }
161
166
  subject { Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}) }
162
167
 
168
+ it_should_behave_like "a task", Taskinator::Task::Step
169
+
163
170
  describe ".define_step_task" do
164
171
  it "sets the queue to use" do
165
172
  task = Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}, :queue => :foo)
@@ -197,8 +204,7 @@ describe Taskinator::Task do
197
204
  expect(args.first).to eq('taskinator.task.enqueued')
198
205
  end
199
206
 
200
- # temporary subscription
201
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
207
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
202
208
  subject.enqueue!
203
209
  end
204
210
  end
@@ -206,7 +212,7 @@ describe Taskinator::Task do
206
212
 
207
213
  describe "#start!" do
208
214
  before do
209
- expect(process).to receive(:task_completed).with(subject)
215
+ allow(process).to receive(:task_completed).with(subject)
210
216
  end
211
217
 
212
218
  it "invokes executor" do
@@ -246,24 +252,28 @@ describe Taskinator::Task do
246
252
  instrumentation_block = SpecSupport::Block.new
247
253
 
248
254
  expect(instrumentation_block).to receive(:call) do |*args|
249
- expect(args.first).to eq('taskinator.task.started')
255
+ expect(args.first).to eq('taskinator.task.processing')
250
256
  end
251
257
 
252
- # special case, since when the method returns, the task is considered to be complete
253
258
  expect(instrumentation_block).to receive(:call) do |*args|
254
259
  expect(args.first).to eq('taskinator.task.completed')
255
260
  end
256
261
 
257
- # temporary subscription
258
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
262
+ TestInstrumenter.subscribe(instrumentation_block) do
259
263
  subject.start!
260
264
  end
261
265
  end
262
266
  end
263
267
 
264
268
  describe "#complete" do
269
+ it "notifies parent process" do
270
+ expect(process).to receive(:task_completed).with(subject)
271
+
272
+ subject.complete!
273
+ end
274
+
265
275
  it "is instrumented" do
266
- allow(process).to receive(:task_completed)
276
+ allow(process).to receive(:task_completed).with(subject)
267
277
 
268
278
  instrumentation_block = SpecSupport::Block.new
269
279
 
@@ -271,8 +281,7 @@ describe Taskinator::Task do
271
281
  expect(args.first).to eq('taskinator.task.completed')
272
282
  end
273
283
 
274
- # temporary subscription
275
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
284
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
276
285
  subject.complete!
277
286
  end
278
287
  end
@@ -294,6 +303,8 @@ describe Taskinator::Task do
294
303
  expect(visitor).to receive(:visit_attribute).with(:method)
295
304
  expect(visitor).to receive(:visit_args).with(:args)
296
305
  expect(visitor).to receive(:visit_attribute).with(:queue)
306
+ expect(visitor).to receive(:visit_attribute_time).with(:created_at)
307
+ expect(visitor).to receive(:visit_attribute_time).with(:updated_at)
297
308
 
298
309
  subject.accept(visitor)
299
310
  }
@@ -311,14 +322,20 @@ describe Taskinator::Task do
311
322
  end
312
323
  end
313
324
 
314
- it_should_behave_like "a task", Taskinator::Task::Job do
315
- let(:process) { Class.new(Taskinator::Process).new(definition) }
316
- let(:task) { Taskinator::Task.define_job_task(process, TestJob, {:a => 1, :b => 2}) }
325
+ class TestJobClass
326
+ def perform(*args)
327
+ end
328
+ end
329
+
330
+ module TestJobModule
331
+ def self.perform(*args)
332
+ end
317
333
  end
318
334
 
319
- let(:process) { Class.new(Taskinator::Process).new(definition) }
320
335
  subject { Taskinator::Task.define_job_task(process, TestJob, {:a => 1, :b => 2}) }
321
336
 
337
+ it_should_behave_like "a task", Taskinator::Task::Job
338
+
322
339
  describe ".define_job_task" do
323
340
  it "sets the queue to use" do
324
341
  task = Taskinator::Task.define_job_task(process, TestJob, {:a => 1, :b => 2}, :queue => :foo)
@@ -330,7 +347,7 @@ describe Taskinator::Task do
330
347
  it {
331
348
  expect {
332
349
  subject.enqueue!
333
- }.to change { Taskinator.queue.jobs.length }.by(1)
350
+ }.to change { Taskinator.queue.tasks.length }.by(1)
334
351
  }
335
352
 
336
353
  it "is instrumented" do
@@ -340,33 +357,36 @@ describe Taskinator::Task do
340
357
  expect(args.first).to eq('taskinator.task.enqueued')
341
358
  end
342
359
 
343
- # temporary subscription
344
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
360
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
345
361
  subject.enqueue!
346
362
  end
347
363
  end
348
364
  end
349
365
 
350
- describe "#perform" do
351
- before do
352
- expect(process).to receive(:task_completed).with(subject)
353
- end
354
-
366
+ describe "#start" do
355
367
  it {
356
- block = SpecSupport::Block.new
357
- expect(block).to receive(:call).with(TestJob, {:a => 1, :b => 2})
368
+ task = Taskinator::Task.define_job_task(process, TestJobClass, {:a => 1, :b => 2})
369
+ expect(process).to receive(:task_completed).with(task)
370
+ expect_any_instance_of(TestJobClass).to receive(:perform).with({:a => 1, :b => 2})
371
+ task.start!
372
+ }
358
373
 
359
- subject.perform(&block)
374
+ it {
375
+ task = Taskinator::Task.define_job_task(process, TestJobModule, {:a => 1, :b => 2})
376
+ expect(process).to receive(:task_completed).with(task)
377
+ expect(TestJobModule).to receive(:perform).with({:a => 1, :b => 2})
378
+ task.start!
360
379
  }
361
380
 
362
381
  it "is instrumented" do
363
- block = SpecSupport::Block.new
364
- allow(block).to receive(:call).with(TestJob, {:a => 1, :b => 2})
382
+ allow(process).to receive(:task_completed).with(subject)
383
+
384
+ allow(TestJob).to receive(:perform).with({:a => 1, :b => 2})
365
385
 
366
386
  instrumentation_block = SpecSupport::Block.new
367
387
 
368
388
  expect(instrumentation_block).to receive(:call) do |*args|
369
- expect(args.first).to eq('taskinator.task.started')
389
+ expect(args.first).to eq('taskinator.task.processing')
370
390
  end
371
391
 
372
392
  # special case, since when the method returns, the task is considered to be complete
@@ -374,16 +394,21 @@ describe Taskinator::Task do
374
394
  expect(args.first).to eq('taskinator.task.completed')
375
395
  end
376
396
 
377
- # temporary subscription
378
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
379
- subject.perform(&block)
397
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
398
+ subject.start!
380
399
  end
381
400
  end
382
401
  end
383
402
 
384
403
  describe "#complete" do
404
+ it "notifies parent process" do
405
+ expect(process).to receive(:task_completed).with(subject)
406
+
407
+ subject.complete!
408
+ end
409
+
385
410
  it "is instrumented" do
386
- allow(process).to receive(:task_completed)
411
+ allow(process).to receive(:task_completed).with(subject)
387
412
 
388
413
  instrumentation_block = SpecSupport::Block.new
389
414
 
@@ -391,8 +416,7 @@ describe Taskinator::Task do
391
416
  expect(args.first).to eq('taskinator.task.completed')
392
417
  end
393
418
 
394
- # temporary subscription
395
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
419
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
396
420
  subject.complete!
397
421
  end
398
422
  end
@@ -414,6 +438,8 @@ describe Taskinator::Task do
414
438
  expect(visitor).to receive(:visit_type).with(:job)
415
439
  expect(visitor).to receive(:visit_args).with(:args)
416
440
  expect(visitor).to receive(:visit_attribute).with(:queue)
441
+ expect(visitor).to receive(:visit_attribute_time).with(:created_at)
442
+ expect(visitor).to receive(:visit_attribute_time).with(:updated_at)
417
443
 
418
444
  subject.accept(visitor)
419
445
  }
@@ -425,16 +451,17 @@ describe Taskinator::Task do
425
451
  end
426
452
 
427
453
  describe Taskinator::Task::SubProcess do
428
- it_should_behave_like "a task", Taskinator::Task::SubProcess do
429
- let(:process) { Class.new(Taskinator::Process).new(definition) }
430
- let(:sub_process) { Class.new(Taskinator::Process).new(definition) }
431
- let(:task) { Taskinator::Task.define_sub_process_task(process, sub_process) }
454
+
455
+ let(:sub_process) do
456
+ Class.new(Taskinator::Process) do
457
+ include ProcessMethods
458
+ end.new(definition)
432
459
  end
433
460
 
434
- let(:process) { Class.new(Taskinator::Process).new(definition) }
435
- let(:sub_process) { Class.new(Taskinator::Process).new(definition) }
436
461
  subject { Taskinator::Task.define_sub_process_task(process, sub_process) }
437
462
 
463
+ it_should_behave_like "a task", Taskinator::Task::SubProcess
464
+
438
465
  describe ".define_sub_process_task" do
439
466
  it "sets the queue to use" do
440
467
  task = Taskinator::Task.define_sub_process_task(process, sub_process, :queue => :foo)
@@ -463,8 +490,7 @@ describe Taskinator::Task do
463
490
  expect(args.first).to eq('taskinator.task.enqueued')
464
491
  end
465
492
 
466
- # temporary subscription
467
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
493
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
468
494
  subject.enqueue!
469
495
  end
470
496
  end
@@ -489,19 +515,24 @@ describe Taskinator::Task do
489
515
  instrumentation_block = SpecSupport::Block.new
490
516
 
491
517
  expect(instrumentation_block).to receive(:call) do |*args|
492
- expect(args.first).to eq('taskinator.task.started')
518
+ expect(args.first).to eq('taskinator.task.processing')
493
519
  end
494
520
 
495
- # temporary subscription
496
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
521
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
497
522
  subject.start!
498
523
  end
499
524
  end
500
525
  end
501
526
 
502
527
  describe "#complete" do
528
+ it "notifies parent process" do
529
+ expect(process).to receive(:task_completed).with(subject)
530
+
531
+ subject.complete!
532
+ end
533
+
503
534
  it "is instrumented" do
504
- allow(process).to receive(:task_completed)
535
+ allow(process).to receive(:task_completed).with(subject)
505
536
 
506
537
  instrumentation_block = SpecSupport::Block.new
507
538
 
@@ -509,8 +540,7 @@ describe Taskinator::Task do
509
540
  expect(args.first).to eq('taskinator.task.completed')
510
541
  end
511
542
 
512
- # temporary subscription
513
- ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
543
+ TestInstrumenter.subscribe(instrumentation_block, /taskinator.task/) do
514
544
  subject.complete!
515
545
  end
516
546
  end
@@ -530,6 +560,8 @@ describe Taskinator::Task do
530
560
  expect(visitor).to receive(:visit_args).with(:options)
531
561
  expect(visitor).to receive(:visit_process).with(:sub_process)
532
562
  expect(visitor).to receive(:visit_attribute).with(:queue)
563
+ expect(visitor).to receive(:visit_attribute_time).with(:created_at)
564
+ expect(visitor).to receive(:visit_attribute_time).with(:updated_at)
533
565
 
534
566
  subject.accept(visitor)
535
567
  }
@@ -6,7 +6,6 @@ describe TestFlows do
6
6
  TestFlows::Task,
7
7
  TestFlows::Job,
8
8
  TestFlows::SubProcess,
9
- TestFlows::Sequential,
10
9
  TestFlows::Sequential
11
10
  ].each do |definition|
12
11
 
@@ -128,4 +127,270 @@ describe TestFlows do
128
127
  end
129
128
  end
130
129
 
130
+ describe "statuses" do
131
+ describe "task" do
132
+ before do
133
+ # override enqueue
134
+ allow_any_instance_of(Taskinator::Task::Step).to receive(:enqueue!) { |task|
135
+ # emulate the worker starting the task
136
+ task.start!
137
+ }
138
+ end
139
+
140
+ let(:task_count) { 2 }
141
+ let(:definition) { TestFlows::Task }
142
+ subject { definition.create_process(task_count) }
143
+
144
+ it "reports process and task state" do
145
+
146
+ instrumenter = TestInstrumenter.new do |name, payload|
147
+
148
+ case name
149
+ when 'taskinator.process.created', 'taskinator.process.saved'
150
+ expect(payload[:state]).to eq(:initial)
151
+ when 'taskinator.process.processing'
152
+ expect(payload[:state]).to eq(:processing)
153
+ when 'taskinator.task.processing'
154
+ expect(payload[:state]).to eq(:processing)
155
+ when 'taskinator.task.completed'
156
+ expect(payload[:state]).to eq(:completed)
157
+ when 'taskinator.process.completed'
158
+ expect(payload[:state]).to eq(:completed)
159
+ else
160
+ raise "Unknown event '#{name}'."
161
+ end
162
+
163
+ end
164
+
165
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
166
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
167
+
168
+ expect(subject.current_state).to eq(:initial)
169
+
170
+ subject.start!
171
+ end
172
+
173
+ end
174
+
175
+ describe "job" do
176
+
177
+ end
178
+
179
+ describe "subprocess" do
180
+
181
+ end
182
+ end
183
+
184
+ describe "instrumentation" do
185
+ describe "task" do
186
+ before do
187
+ # override enqueue
188
+ allow_any_instance_of(Taskinator::Task::Step).to receive(:enqueue!) { |task|
189
+ # emulate the worker starting the task
190
+ task.start!
191
+ }
192
+ end
193
+
194
+ let(:task_count) { 10 }
195
+ let(:definition) { TestFlows::Task }
196
+ subject { definition.create_process(task_count) }
197
+
198
+ it "reports task completed" do
199
+ block = SpecSupport::Block.new
200
+ expect(block).to receive(:call).exactly(task_count).times
201
+
202
+ TestInstrumenter.subscribe(block, /taskinator.task.completed/) do
203
+ subject.start!
204
+ end
205
+ end
206
+
207
+ it "reports process completed" do
208
+ block = SpecSupport::Block.new
209
+ expect(block).to receive(:call).once
210
+
211
+ TestInstrumenter.subscribe(block, /taskinator.process.completed/) do
212
+ subject.start!
213
+ end
214
+ end
215
+
216
+ it "reports task percentage completed" do
217
+ invoke_count = 0
218
+
219
+ instrumenter = TestInstrumenter.new do |name, payload|
220
+ if name =~ /taskinator.task.processing/
221
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
222
+ elsif name =~ /taskinator.task.completed/
223
+ invoke_count += 1
224
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
225
+ end
226
+ end
227
+
228
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
229
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
230
+
231
+ subject.start!
232
+ end
233
+
234
+ it "reports process percentage completed" do
235
+ instrumenter = TestInstrumenter.new do |name, payload|
236
+ if name =~ /taskinator.process.started/
237
+ expect(payload[:process_uuid]).to eq(subject.uuid)
238
+ elsif name =~ /taskinator.process.completed/
239
+ expect(payload[:percentage_completed]).to eq(100.0)
240
+ end
241
+ end
242
+
243
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
244
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
245
+
246
+ subject.start!
247
+ end
248
+
249
+ end
250
+
251
+ describe "job" do
252
+ before do
253
+ # override enqueue
254
+ allow_any_instance_of(Taskinator::Task::Job).to receive(:enqueue!) { |task|
255
+ # emulate the worker starting the task
256
+ task.start!
257
+ }
258
+ end
259
+
260
+ let(:task_count) { 10 }
261
+ let(:definition) { TestFlows::Job }
262
+ subject { definition.create_process(task_count) }
263
+
264
+ it "reports task completed" do
265
+ block = SpecSupport::Block.new
266
+ expect(block).to receive(:call).exactly(task_count).times
267
+
268
+ TestInstrumenter.subscribe(block, /taskinator.task.completed/) do
269
+ subject.start!
270
+ end
271
+ end
272
+
273
+ it "reports process completed" do
274
+ block = SpecSupport::Block.new
275
+ expect(block).to receive(:call).once
276
+
277
+ TestInstrumenter.subscribe(block, /taskinator.process.completed/) do
278
+ subject.start!
279
+ end
280
+ end
281
+
282
+ it "reports task percentage completed" do
283
+ invoke_count = 0
284
+
285
+ instrumenter = TestInstrumenter.new do |name, payload|
286
+ if name =~ /taskinator.task.processing/
287
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
288
+ elsif name =~ /taskinator.task.completed/
289
+ invoke_count += 1
290
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
291
+ end
292
+ end
293
+
294
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
295
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
296
+
297
+ subject.start!
298
+ end
299
+
300
+ it "reports process percentage completed" do
301
+ instrumenter = TestInstrumenter.new do |name, payload|
302
+ if name =~ /taskinator.process.started/
303
+ expect(payload[:process_uuid]).to eq(subject.uuid)
304
+ elsif name =~ /taskinator.process.completed/
305
+ expect(payload[:percentage_completed]).to eq(100.0)
306
+ end
307
+ end
308
+
309
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
310
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
311
+
312
+ subject.start!
313
+ end
314
+
315
+ end
316
+
317
+ describe "sub process" do
318
+ before do
319
+ # override enqueue
320
+ allow_any_instance_of(Taskinator::Task::Step).to receive(:enqueue!) { |task|
321
+ # emulate the worker starting the task
322
+ task.start!
323
+ }
324
+
325
+ # override enqueue
326
+ allow_any_instance_of(Taskinator::Task::SubProcess).to receive(:enqueue!) { |task|
327
+ # emulate the worker starting the task
328
+ task.start!
329
+ }
330
+ end
331
+
332
+ let(:task_count) { 10 }
333
+ let(:definition) { TestFlows::SubProcess }
334
+ subject { definition.create_process(task_count) }
335
+
336
+ it "reports task completed" do
337
+ block = SpecSupport::Block.new
338
+
339
+ # NOTE: sub process counts for one task
340
+ expect(block).to receive(:call).exactly(task_count + 1).times
341
+
342
+ TestInstrumenter.subscribe(block, /taskinator.task.completed/) do
343
+ subject.start!
344
+ end
345
+ end
346
+
347
+ it "reports process completed" do
348
+ block = SpecSupport::Block.new
349
+ expect(block).to receive(:call).twice # includes sub process
350
+
351
+ TestInstrumenter.subscribe(block, /taskinator.process.completed/) do
352
+ subject.start!
353
+ end
354
+ end
355
+
356
+ it "reports task percentage completed" do
357
+ invoke_count = 0
358
+
359
+ instrumenter = TestInstrumenter.new do |name, payload|
360
+ if name =~ /taskinator.task.processing/
361
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
362
+ elsif name =~ /taskinator.task.completed/
363
+ unless payload.type >= Taskinator::Task::SubProcess
364
+ invoke_count += 1
365
+ expect(payload[:percentage_completed]).to eq( (invoke_count / task_count.to_f) * 100.0 )
366
+ end
367
+ end
368
+ end
369
+
370
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
371
+ expect(instrumenter).to receive(:instrument).at_least(task_count).times.and_call_original
372
+
373
+ subject.start!
374
+ end
375
+
376
+ it "reports process percentage completed" do
377
+ instrumenter = TestInstrumenter.new do |name, payload|
378
+ if name =~ /taskinator.process.started/
379
+ expect(payload[:process_uuid]).to eq(subject.uuid)
380
+ elsif name =~ /taskinator.process.completed/
381
+ expect(payload[:percentage_completed]).to eq(100.0)
382
+ end
383
+ end
384
+
385
+ allow(Taskinator).to receive(:instrumenter).and_return(instrumenter)
386
+
387
+ # NOTE: sub process counts for one task
388
+ expect(instrumenter).to receive(:instrument).at_least(task_count + 1).times.and_call_original
389
+
390
+ subject.start!
391
+ end
392
+
393
+ end
394
+ end
395
+
131
396
  end
data/taskinator.gemspec CHANGED
@@ -25,25 +25,4 @@ Gem::Specification.new do |spec|
25
25
  spec.add_dependency 'redis-namespace' , '>= 1.5.2'
26
26
  spec.add_dependency 'connection_pool' , '>= 2.2.0'
27
27
  spec.add_dependency 'json' , '>= 1.8.2'
28
-
29
- # spec.add_dependency 'workflow' , '>= 1.3.0' # RubyGems not up to date as of 11 Nov 2014.
30
-
31
- # queues
32
- spec.add_development_dependency 'sidekiq' , '>= 3.0.0'
33
- spec.add_development_dependency 'rspec-sidekiq' , '>= 2.0.0'
34
-
35
- spec.add_development_dependency 'delayed_job' , '>= 4.0.0'
36
-
37
- spec.add_development_dependency 'resque' , '>= 1.25.2'
38
- spec.add_development_dependency 'resque_spec' , '>= 0.16.0'
39
-
40
- # other
41
- spec.add_development_dependency 'bundler' , '>= 1.6.0'
42
- spec.add_development_dependency 'rake' , '>= 10.3.0'
43
- spec.add_development_dependency 'activesupport' , '>= 4.0.0'
44
- spec.add_development_dependency 'rspec'
45
- spec.add_development_dependency 'coveralls' , '>= 0.7.0'
46
- spec.add_development_dependency 'pry' , '>= 0.9.0'
47
- spec.add_development_dependency 'pry-byebug' , '>= 1.3.0'
48
-
49
28
  end