taskinator 0.0.18 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +28 -28
- data/README.md +29 -0
- data/Rakefile +5 -0
- data/bin/console +5 -0
- data/lib/taskinator/create_process_worker.rb +5 -2
- data/lib/taskinator/definition/builder.rb +12 -7
- data/lib/taskinator/definition.rb +36 -28
- data/lib/taskinator/executor.rb +4 -4
- data/lib/taskinator/job_worker.rb +5 -10
- data/lib/taskinator/logger.rb +1 -0
- data/lib/taskinator/persistence.rb +74 -36
- data/lib/taskinator/process.rb +75 -49
- data/lib/taskinator/queues/delayed_job.rb +1 -11
- data/lib/taskinator/queues/resque.rb +0 -15
- data/lib/taskinator/queues/sidekiq.rb +1 -14
- data/lib/taskinator/queues.rb +0 -5
- data/lib/taskinator/redis_connection.rb +1 -0
- data/lib/taskinator/task.rb +57 -57
- data/lib/taskinator/task_worker.rb +1 -8
- data/lib/taskinator/version.rb +1 -1
- data/lib/taskinator.rb +7 -6
- data/spec/examples/queue_adapter_examples.rb +0 -10
- data/spec/support/test_definition.rb +4 -0
- data/spec/support/test_flow.rb +2 -0
- data/spec/support/test_flows.rb +54 -3
- data/spec/support/test_queue.rb +41 -6
- data/spec/taskinator/create_process_worker_spec.rb +12 -3
- data/spec/taskinator/definition/builder_spec.rb +39 -9
- data/spec/taskinator/definition_spec.rb +19 -27
- data/spec/taskinator/executor_spec.rb +19 -1
- data/spec/taskinator/job_worker_spec.rb +0 -11
- data/spec/taskinator/persistence_spec.rb +122 -7
- data/spec/taskinator/process_spec.rb +39 -23
- data/spec/taskinator/queues/delayed_job_spec.rb +1 -19
- data/spec/taskinator/queues/resque_spec.rb +1 -22
- data/spec/taskinator/queues/sidekiq_spec.rb +1 -20
- data/spec/taskinator/task_spec.rb +160 -52
- data/spec/taskinator/task_worker_spec.rb +0 -17
- data/spec/taskinator/test_flows_spec.rb +43 -0
- metadata +2 -5
- data/lib/taskinator/process_worker.rb +0 -21
- data/spec/taskinator/process_worker_spec.rb +0 -51
@@ -74,20 +74,6 @@ describe Taskinator::Process do
|
|
74
74
|
subject.enqueue!
|
75
75
|
expect(subject.current_state.name).to eq(:enqueued)
|
76
76
|
}
|
77
|
-
|
78
|
-
it "should not enqueue if there aren't any tasks" do
|
79
|
-
expect {
|
80
|
-
subject.enqueue!
|
81
|
-
}.to change { Taskinator.queue.processes.length }.by(0)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should enqueue if there are tasks" do
|
85
|
-
allow(subject).to receive(:tasks).and_return([Object.new])
|
86
|
-
|
87
|
-
expect {
|
88
|
-
subject.enqueue!
|
89
|
-
}.to change { Taskinator.queue.processes.length }.by(1)
|
90
|
-
end
|
91
77
|
end
|
92
78
|
|
93
79
|
describe "#start!" do
|
@@ -155,7 +141,6 @@ describe Taskinator::Process do
|
|
155
141
|
subject.complete!
|
156
142
|
}
|
157
143
|
it {
|
158
|
-
expect(subject).to receive(:tasks_completed?) { true }
|
159
144
|
subject.start!
|
160
145
|
subject.complete!
|
161
146
|
expect(subject.current_state.name).to eq(:completed)
|
@@ -216,10 +201,6 @@ describe Taskinator::Process do
|
|
216
201
|
}
|
217
202
|
end
|
218
203
|
|
219
|
-
describe "#reload" do
|
220
|
-
it { expect(subject.reload).to_not be }
|
221
|
-
end
|
222
|
-
|
223
204
|
describe "#tasks_count" do
|
224
205
|
it {
|
225
206
|
expect(subject.tasks_count).to eq(0)
|
@@ -262,13 +243,31 @@ describe Taskinator::Process do
|
|
262
243
|
end
|
263
244
|
end
|
264
245
|
|
246
|
+
describe "#enqueue!" do
|
247
|
+
context "without tasks" do
|
248
|
+
it {
|
249
|
+
expect {
|
250
|
+
subject.enqueue!
|
251
|
+
}.to change { Taskinator.queue.tasks.length }.by(0)
|
252
|
+
}
|
253
|
+
end
|
254
|
+
|
255
|
+
it "delegates to the first task" do
|
256
|
+
task = double('task')
|
257
|
+
expect(task).to receive(:enqueue!)
|
258
|
+
allow(subject).to receive(:tasks).and_return([task])
|
259
|
+
|
260
|
+
subject.enqueue!
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
265
264
|
describe "#start!" do
|
266
265
|
it "executes the first task" do
|
267
266
|
tasks.each {|t| subject.tasks << t }
|
268
267
|
task1 = tasks[0]
|
269
268
|
|
270
269
|
expect(subject.tasks).to receive(:first).and_call_original
|
271
|
-
expect(task1).to receive(:
|
270
|
+
expect(task1).to receive(:start!)
|
272
271
|
|
273
272
|
subject.start!
|
274
273
|
end
|
@@ -295,7 +294,6 @@ describe Taskinator::Process do
|
|
295
294
|
tasks.each {|t| subject.tasks << t }
|
296
295
|
task2 = tasks[1]
|
297
296
|
|
298
|
-
expect(subject).to receive(:can_complete?) { true }
|
299
297
|
expect(subject).to receive(:complete!)
|
300
298
|
|
301
299
|
subject.task_completed(task2)
|
@@ -380,11 +378,30 @@ describe Taskinator::Process do
|
|
380
378
|
end
|
381
379
|
end
|
382
380
|
|
381
|
+
describe "#enqueue!" do
|
382
|
+
context "without tasks" do
|
383
|
+
it {
|
384
|
+
expect {
|
385
|
+
subject.enqueue!
|
386
|
+
}.to change { Taskinator.queue.tasks.length }.by(0)
|
387
|
+
}
|
388
|
+
end
|
389
|
+
|
390
|
+
it "delegates to all the tasks" do
|
391
|
+
tasks.each {|t|
|
392
|
+
subject.tasks << t
|
393
|
+
expect(t).to receive(:enqueue!)
|
394
|
+
}
|
395
|
+
|
396
|
+
subject.enqueue!
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
383
400
|
describe "#start!" do
|
384
401
|
it "executes all tasks" do
|
385
402
|
tasks.each {|t|
|
386
403
|
subject.tasks << t
|
387
|
-
expect(t).to receive(:
|
404
|
+
expect(t).to receive(:start!)
|
388
405
|
}
|
389
406
|
|
390
407
|
subject.start!
|
@@ -400,7 +417,6 @@ describe Taskinator::Process do
|
|
400
417
|
it "completes when tasks complete" do
|
401
418
|
tasks.each {|t| subject.tasks << t }
|
402
419
|
|
403
|
-
expect(subject).to receive(:can_complete?) { true }
|
404
420
|
expect(subject).to receive(:complete!)
|
405
421
|
|
406
422
|
subject.task_completed(tasks.first)
|
@@ -30,24 +30,6 @@ describe Taskinator::Queues::DelayedJobAdapter, :delayed_job do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
describe "ProcessWorker" do
|
34
|
-
it "enqueues processes" do
|
35
|
-
expect {
|
36
|
-
subject.enqueue_process(double('process', :uuid => uuid, :queue => nil))
|
37
|
-
}.to change(Delayed::Job.queue, :size).by(1)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "enqueues process to specified queue" do
|
41
|
-
subject.enqueue_process(double('process', :uuid => uuid, :queue => :other))
|
42
|
-
expect(Delayed::Job.contains?(adapter::ProcessWorker, uuid, :other)).to be
|
43
|
-
end
|
44
|
-
|
45
|
-
it "calls process worker" do
|
46
|
-
expect_any_instance_of(Taskinator::ProcessWorker).to receive(:perform)
|
47
|
-
adapter::ProcessWorker.new(uuid).perform
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
33
|
describe "TaskWorker" do
|
52
34
|
it "enqueues tasks" do
|
53
35
|
expect {
|
@@ -92,7 +74,7 @@ describe Taskinator::Queues::DelayedJobAdapter, :delayed_job do
|
|
92
74
|
let(:definition) { TestDefinition }
|
93
75
|
|
94
76
|
it "performs invocation on job" do
|
95
|
-
args = {:a => 1}
|
77
|
+
args = [:foo, {:a => 1}]
|
96
78
|
job = double('job')
|
97
79
|
expect(job).to receive(:perform)
|
98
80
|
|
@@ -34,27 +34,6 @@ describe Taskinator::Queues::ResqueAdapter, :resque do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
describe "ProcessWorker" do
|
38
|
-
it "enqueues processes" do
|
39
|
-
worker = adapter::ProcessWorker
|
40
|
-
subject.enqueue_process(double('process', :uuid => uuid, :queue => nil))
|
41
|
-
|
42
|
-
expect(worker).to have_queued(uuid)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "enqueues process to specified queue" do
|
46
|
-
worker = adapter::ProcessWorker
|
47
|
-
subject.enqueue_process(double('process', :uuid => uuid, :queue => :other))
|
48
|
-
|
49
|
-
expect(worker).to have_queued(uuid).in(:other)
|
50
|
-
end
|
51
|
-
|
52
|
-
it "calls process worker" do
|
53
|
-
expect_any_instance_of(Taskinator::ProcessWorker).to receive(:perform)
|
54
|
-
adapter::ProcessWorker.perform(uuid)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
37
|
describe "TaskWorker" do
|
59
38
|
it "enqueues tasks" do
|
60
39
|
worker = adapter::TaskWorker
|
@@ -115,7 +94,7 @@ describe Taskinator::Queues::ResqueAdapter, :resque do
|
|
115
94
|
let(:definition) { TestDefinition }
|
116
95
|
|
117
96
|
it "performs invocation on job" do
|
118
|
-
args = {:a => 1}
|
97
|
+
args = [:foo, {:a => 1}]
|
119
98
|
job_class = double('job_class', :methods => [:perform])
|
120
99
|
expect(job_class).to receive(:perform).with(*args)
|
121
100
|
|
@@ -33,25 +33,6 @@ describe Taskinator::Queues::SidekiqAdapter, :sidekiq do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
describe "ProcessWorker" do
|
37
|
-
it "enqueues processes" do
|
38
|
-
worker = adapter::ProcessWorker
|
39
|
-
process = double('process', :uuid => uuid, :queue => nil)
|
40
|
-
subject.enqueue_process(process)
|
41
|
-
expect(worker).to have_enqueued_job(process.uuid)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "enqueues process to specified queue" do
|
45
|
-
subject.enqueue_process(double('process', :uuid => uuid, :queue => :other))
|
46
|
-
expect(adapter::ProcessWorker).to be_processed_in_x(:other)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "calls process worker" do
|
50
|
-
expect_any_instance_of(Taskinator::ProcessWorker).to receive(:perform)
|
51
|
-
adapter::ProcessWorker.new.perform(uuid)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
36
|
describe "TaskWorker" do
|
56
37
|
it "enqueues tasks" do
|
57
38
|
worker = adapter::TaskWorker
|
@@ -106,7 +87,7 @@ describe Taskinator::Queues::SidekiqAdapter, :sidekiq do
|
|
106
87
|
let(:definition) { TestDefinition }
|
107
88
|
|
108
89
|
it "performs invocation on job" do
|
109
|
-
args = {:a => 1}
|
90
|
+
args = [:foo, {:a => 1}]
|
110
91
|
job = double('job')
|
111
92
|
expect(job).to receive(:perform).with(*args)
|
112
93
|
|
@@ -7,6 +7,7 @@ describe Taskinator::Task do
|
|
7
7
|
describe "Base" do
|
8
8
|
|
9
9
|
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
10
|
+
|
10
11
|
subject { Class.new(Taskinator::Task).new(process) }
|
11
12
|
|
12
13
|
describe "#initialize" do
|
@@ -49,14 +50,6 @@ describe Taskinator::Task do
|
|
49
50
|
it { expect(subject.current_state.name).to eq(:initial) }
|
50
51
|
end
|
51
52
|
|
52
|
-
describe "#can_complete_task?" do
|
53
|
-
it {
|
54
|
-
expect {
|
55
|
-
subject.can_complete_task?
|
56
|
-
}.to raise_error(NotImplementedError)
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
53
|
describe "workflow" do
|
61
54
|
describe "#enqueue!" do
|
62
55
|
it { expect(subject).to respond_to(:enqueue!) }
|
@@ -68,11 +61,6 @@ describe Taskinator::Task do
|
|
68
61
|
subject.enqueue!
|
69
62
|
expect(subject.current_state.name).to eq(:enqueued)
|
70
63
|
}
|
71
|
-
it {
|
72
|
-
expect {
|
73
|
-
subject.enqueue!
|
74
|
-
}.to change { Taskinator.queue.tasks.length }.by(1)
|
75
|
-
}
|
76
64
|
end
|
77
65
|
|
78
66
|
describe "#start!" do
|
@@ -90,9 +78,7 @@ describe Taskinator::Task do
|
|
90
78
|
describe "#complete!" do
|
91
79
|
it { expect(subject).to respond_to(:complete!) }
|
92
80
|
it {
|
93
|
-
expect(subject).to receive(:can_complete_task?) { true }
|
94
81
|
expect(subject).to receive(:complete)
|
95
|
-
expect(process).to receive(:task_completed).with(subject)
|
96
82
|
subject.start!
|
97
83
|
subject.complete!
|
98
84
|
expect(subject.current_state.name).to eq(:completed)
|
@@ -158,10 +144,6 @@ describe Taskinator::Task do
|
|
158
144
|
}
|
159
145
|
end
|
160
146
|
|
161
|
-
describe "#reload" do
|
162
|
-
it { expect(subject.reload).to_not be }
|
163
|
-
end
|
164
|
-
|
165
147
|
describe "#tasks_count" do
|
166
148
|
it {
|
167
149
|
expect(subject.tasks_count).to eq(0)
|
@@ -172,15 +154,15 @@ describe Taskinator::Task do
|
|
172
154
|
describe Taskinator::Task::Step do
|
173
155
|
it_should_behave_like "a task", Taskinator::Task::Step do
|
174
156
|
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
175
|
-
let(:task) { Taskinator::Task.define_step_task(process, :
|
157
|
+
let(:task) { Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}) }
|
176
158
|
end
|
177
159
|
|
178
160
|
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
179
|
-
subject { Taskinator::Task.define_step_task(process, :
|
161
|
+
subject { Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}) }
|
180
162
|
|
181
163
|
describe ".define_step_task" do
|
182
164
|
it "sets the queue to use" do
|
183
|
-
task = Taskinator::Task.define_step_task(process, :
|
165
|
+
task = Taskinator::Task.define_step_task(process, :do_task, {:a => 1, :b => 2}, :queue => :foo)
|
184
166
|
expect(task.queue).to eq(:foo)
|
185
167
|
end
|
186
168
|
end
|
@@ -188,18 +170,47 @@ describe Taskinator::Task do
|
|
188
170
|
describe "#executor" do
|
189
171
|
it { expect(subject.executor).to_not be_nil }
|
190
172
|
it { expect(subject.executor).to be_a(definition) }
|
191
|
-
end
|
192
|
-
|
193
|
-
describe "#start!" do
|
194
|
-
it "invokes executor" do
|
195
|
-
expect(subject.executor).to receive(subject.method).with(*subject.args)
|
196
|
-
subject.start!
|
197
|
-
end
|
198
173
|
|
199
174
|
it "handles failure" do
|
200
175
|
error = StandardError.new
|
201
176
|
allow(subject.executor).to receive(subject.method).with(*subject.args).and_raise(error)
|
202
177
|
expect(subject).to receive(:fail!).with(error)
|
178
|
+
expect {
|
179
|
+
subject.start!
|
180
|
+
}.to raise_error(error)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#enqueue!" do
|
185
|
+
it {
|
186
|
+
expect {
|
187
|
+
subject.enqueue!
|
188
|
+
}.to change { Taskinator.queue.tasks.length }.by(1)
|
189
|
+
}
|
190
|
+
|
191
|
+
it "is instrumented" do
|
192
|
+
allow(subject.executor).to receive(subject.method).with(*subject.args)
|
193
|
+
|
194
|
+
instrumentation_block = SpecSupport::Block.new
|
195
|
+
|
196
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
197
|
+
expect(args.first).to eq('taskinator.task.enqueued')
|
198
|
+
end
|
199
|
+
|
200
|
+
# temporary subscription
|
201
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
202
|
+
subject.enqueue!
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "#start!" do
|
208
|
+
before do
|
209
|
+
expect(process).to receive(:task_completed).with(subject)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "invokes executor" do
|
213
|
+
expect(subject.executor).to receive(subject.method).with(*subject.args)
|
203
214
|
subject.start!
|
204
215
|
end
|
205
216
|
|
@@ -232,25 +243,39 @@ describe Taskinator::Task do
|
|
232
243
|
end
|
233
244
|
|
234
245
|
it "is instrumented" do
|
235
|
-
allow(subject.executor).to receive(subject.method)
|
236
|
-
|
237
246
|
instrumentation_block = SpecSupport::Block.new
|
238
|
-
|
247
|
+
|
248
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
249
|
+
expect(args.first).to eq('taskinator.task.started')
|
250
|
+
end
|
251
|
+
|
252
|
+
# special case, since when the method returns, the task is considered to be complete
|
253
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
254
|
+
expect(args.first).to eq('taskinator.task.completed')
|
255
|
+
end
|
239
256
|
|
240
257
|
# temporary subscription
|
241
|
-
ActiveSupport::Notifications.subscribed(instrumentation_block, /
|
258
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
242
259
|
subject.start!
|
243
260
|
end
|
244
261
|
end
|
245
262
|
end
|
246
263
|
|
247
|
-
describe "#
|
248
|
-
it
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
264
|
+
describe "#complete" do
|
265
|
+
it "is instrumented" do
|
266
|
+
allow(process).to receive(:task_completed)
|
267
|
+
|
268
|
+
instrumentation_block = SpecSupport::Block.new
|
269
|
+
|
270
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
271
|
+
expect(args.first).to eq('taskinator.task.completed')
|
272
|
+
end
|
273
|
+
|
274
|
+
# temporary subscription
|
275
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
276
|
+
subject.complete!
|
277
|
+
end
|
278
|
+
end
|
254
279
|
end
|
255
280
|
|
256
281
|
describe "#accept" do
|
@@ -307,9 +332,26 @@ describe Taskinator::Task do
|
|
307
332
|
subject.enqueue!
|
308
333
|
}.to change { Taskinator.queue.jobs.length }.by(1)
|
309
334
|
}
|
335
|
+
|
336
|
+
it "is instrumented" do
|
337
|
+
instrumentation_block = SpecSupport::Block.new
|
338
|
+
|
339
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
340
|
+
expect(args.first).to eq('taskinator.task.enqueued')
|
341
|
+
end
|
342
|
+
|
343
|
+
# temporary subscription
|
344
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
345
|
+
subject.enqueue!
|
346
|
+
end
|
347
|
+
end
|
310
348
|
end
|
311
349
|
|
312
350
|
describe "#perform" do
|
351
|
+
before do
|
352
|
+
expect(process).to receive(:task_completed).with(subject)
|
353
|
+
end
|
354
|
+
|
313
355
|
it {
|
314
356
|
block = SpecSupport::Block.new
|
315
357
|
expect(block).to receive(:call).with(TestJob, {:a => 1, :b => 2})
|
@@ -319,18 +361,43 @@ describe Taskinator::Task do
|
|
319
361
|
|
320
362
|
it "is instrumented" do
|
321
363
|
block = SpecSupport::Block.new
|
322
|
-
allow(block).to receive(:call)
|
364
|
+
allow(block).to receive(:call).with(TestJob, {:a => 1, :b => 2})
|
323
365
|
|
324
366
|
instrumentation_block = SpecSupport::Block.new
|
325
|
-
|
367
|
+
|
368
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
369
|
+
expect(args.first).to eq('taskinator.task.started')
|
370
|
+
end
|
371
|
+
|
372
|
+
# special case, since when the method returns, the task is considered to be complete
|
373
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
374
|
+
expect(args.first).to eq('taskinator.task.completed')
|
375
|
+
end
|
326
376
|
|
327
377
|
# temporary subscription
|
328
|
-
ActiveSupport::Notifications.subscribed(instrumentation_block, /
|
378
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
329
379
|
subject.perform(&block)
|
330
380
|
end
|
331
381
|
end
|
332
382
|
end
|
333
383
|
|
384
|
+
describe "#complete" do
|
385
|
+
it "is instrumented" do
|
386
|
+
allow(process).to receive(:task_completed)
|
387
|
+
|
388
|
+
instrumentation_block = SpecSupport::Block.new
|
389
|
+
|
390
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
391
|
+
expect(args.first).to eq('taskinator.task.completed')
|
392
|
+
end
|
393
|
+
|
394
|
+
# temporary subscription
|
395
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
396
|
+
subject.complete!
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
334
401
|
describe "#accept" do
|
335
402
|
it {
|
336
403
|
expect(subject).to receive(:accept)
|
@@ -375,6 +442,34 @@ describe Taskinator::Task do
|
|
375
442
|
end
|
376
443
|
end
|
377
444
|
|
445
|
+
describe "#enqueue!" do
|
446
|
+
context "without tasks" do
|
447
|
+
it {
|
448
|
+
expect {
|
449
|
+
subject.enqueue!
|
450
|
+
}.to change { Taskinator.queue.tasks.length }.by(0)
|
451
|
+
}
|
452
|
+
end
|
453
|
+
|
454
|
+
it "delegates to sub process" do
|
455
|
+
expect(sub_process).to receive(:enqueue!)
|
456
|
+
subject.enqueue!
|
457
|
+
end
|
458
|
+
|
459
|
+
it "is instrumented" do
|
460
|
+
instrumentation_block = SpecSupport::Block.new
|
461
|
+
|
462
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
463
|
+
expect(args.first).to eq('taskinator.task.enqueued')
|
464
|
+
end
|
465
|
+
|
466
|
+
# temporary subscription
|
467
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
468
|
+
subject.enqueue!
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
378
473
|
describe "#start!" do
|
379
474
|
it "delegates to sub process" do
|
380
475
|
expect(sub_process).to receive(:start)
|
@@ -385,26 +480,39 @@ describe Taskinator::Task do
|
|
385
480
|
error = StandardError.new
|
386
481
|
allow(sub_process).to receive(:start!).and_raise(error)
|
387
482
|
expect(subject).to receive(:fail!).with(error)
|
388
|
-
|
483
|
+
expect {
|
484
|
+
subject.start!
|
485
|
+
}.to raise_error(error)
|
389
486
|
end
|
390
487
|
|
391
488
|
it "is instrumented" do
|
392
|
-
allow(sub_process).to receive(:start)
|
393
|
-
|
394
489
|
instrumentation_block = SpecSupport::Block.new
|
395
|
-
|
490
|
+
|
491
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
492
|
+
expect(args.first).to eq('taskinator.task.started')
|
493
|
+
end
|
396
494
|
|
397
495
|
# temporary subscription
|
398
|
-
ActiveSupport::Notifications.subscribed(instrumentation_block, /
|
496
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
399
497
|
subject.start!
|
400
498
|
end
|
401
499
|
end
|
402
500
|
end
|
403
501
|
|
404
|
-
describe "#
|
405
|
-
it "
|
406
|
-
|
407
|
-
|
502
|
+
describe "#complete" do
|
503
|
+
it "is instrumented" do
|
504
|
+
allow(process).to receive(:task_completed)
|
505
|
+
|
506
|
+
instrumentation_block = SpecSupport::Block.new
|
507
|
+
|
508
|
+
expect(instrumentation_block).to receive(:call) do |*args|
|
509
|
+
expect(args.first).to eq('taskinator.task.completed')
|
510
|
+
end
|
511
|
+
|
512
|
+
# temporary subscription
|
513
|
+
ActiveSupport::Notifications.subscribed(instrumentation_block, /taskinator.task/) do
|
514
|
+
subject.complete!
|
515
|
+
end
|
408
516
|
end
|
409
517
|
end
|
410
518
|
|
@@ -24,22 +24,6 @@ describe Taskinator::TaskWorker do
|
|
24
24
|
subject.perform
|
25
25
|
end
|
26
26
|
|
27
|
-
it "should complete the task if can_complete? is true" do
|
28
|
-
task = mock_task(false, false, true)
|
29
|
-
allow(Taskinator::Task).to receive(:fetch).with(uuid) { task }
|
30
|
-
allow(task).to receive(:start!)
|
31
|
-
expect(task).to receive(:complete!)
|
32
|
-
subject.perform
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should not complete the task if can_complete? is false" do
|
36
|
-
task = mock_task
|
37
|
-
allow(Taskinator::Task).to receive(:fetch).with(uuid) { task }
|
38
|
-
allow(task).to receive(:start!)
|
39
|
-
expect(task).to_not receive(:complete!)
|
40
|
-
subject.perform
|
41
|
-
end
|
42
|
-
|
43
27
|
it "should not start if paused" do
|
44
28
|
task = mock_task(true, false)
|
45
29
|
allow(Taskinator::Task).to receive(:fetch).with(uuid) { task }
|
@@ -58,7 +42,6 @@ describe Taskinator::TaskWorker do
|
|
58
42
|
task = mock_task
|
59
43
|
allow(Taskinator::Task).to receive(:fetch).with(uuid) { task }
|
60
44
|
allow(task).to receive(:start!) { raise StandardError }
|
61
|
-
expect(task).to receive(:fail!).with(StandardError)
|
62
45
|
expect {
|
63
46
|
subject.perform
|
64
47
|
}.to raise_error(StandardError)
|
@@ -85,4 +85,47 @@ describe TestFlows do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
+
|
89
|
+
describe "scenarios" do
|
90
|
+
|
91
|
+
before do
|
92
|
+
# use the "synchronous" queue
|
93
|
+
Taskinator.queue_adapter = :test_queue_worker
|
94
|
+
end
|
95
|
+
|
96
|
+
context "empty subprocesses" do
|
97
|
+
|
98
|
+
context "sequential" do
|
99
|
+
let(:definition) { TestFlows::EmptySequentialProcessTest }
|
100
|
+
subject { definition.create_process }
|
101
|
+
|
102
|
+
it "invokes each task" do
|
103
|
+
# this doesn't work...
|
104
|
+
# expect_any_instance_of(Taskinator::Executor).to receive(:do_task_x).exactly(3).times
|
105
|
+
# subject.start!
|
106
|
+
|
107
|
+
expect {
|
108
|
+
subject.enqueue!
|
109
|
+
}.to change { Taskinator.queue.tasks.length }.by(3)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "concurrent" do
|
114
|
+
let(:definition) { TestFlows::EmptyConcurrentProcessTest }
|
115
|
+
subject { definition.create_process }
|
116
|
+
|
117
|
+
it "invokes each task" do
|
118
|
+
# this doesn't work...
|
119
|
+
# expect_any_instance_of(Taskinator::Executor).to receive(:do_task_x).exactly(3).times
|
120
|
+
# subject.start!
|
121
|
+
|
122
|
+
expect {
|
123
|
+
subject.enqueue!
|
124
|
+
}.to change { Taskinator.queue.tasks.length }.by(3)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
88
131
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taskinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Stefano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -268,7 +268,6 @@ files:
|
|
268
268
|
- lib/taskinator/logger.rb
|
269
269
|
- lib/taskinator/persistence.rb
|
270
270
|
- lib/taskinator/process.rb
|
271
|
-
- lib/taskinator/process_worker.rb
|
272
271
|
- lib/taskinator/queues.rb
|
273
272
|
- lib/taskinator/queues/delayed_job.rb
|
274
273
|
- lib/taskinator/queues/resque.rb
|
@@ -305,7 +304,6 @@ files:
|
|
305
304
|
- spec/taskinator/job_worker_spec.rb
|
306
305
|
- spec/taskinator/persistence_spec.rb
|
307
306
|
- spec/taskinator/process_spec.rb
|
308
|
-
- spec/taskinator/process_worker_spec.rb
|
309
307
|
- spec/taskinator/queues/delayed_job_spec.rb
|
310
308
|
- spec/taskinator/queues/resque_spec.rb
|
311
309
|
- spec/taskinator/queues/sidekiq_spec.rb
|
@@ -368,7 +366,6 @@ test_files:
|
|
368
366
|
- spec/taskinator/job_worker_spec.rb
|
369
367
|
- spec/taskinator/persistence_spec.rb
|
370
368
|
- spec/taskinator/process_spec.rb
|
371
|
-
- spec/taskinator/process_worker_spec.rb
|
372
369
|
- spec/taskinator/queues/delayed_job_spec.rb
|
373
370
|
- spec/taskinator/queues/resque_spec.rb
|
374
371
|
- spec/taskinator/queues/sidekiq_spec.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Taskinator
|
2
|
-
class ProcessWorker
|
3
|
-
attr_reader :uuid
|
4
|
-
|
5
|
-
def initialize(uuid)
|
6
|
-
@uuid = uuid
|
7
|
-
end
|
8
|
-
|
9
|
-
def perform
|
10
|
-
process = Taskinator::Process.fetch(@uuid)
|
11
|
-
return if process.paused? || process.cancelled?
|
12
|
-
begin
|
13
|
-
process.start!
|
14
|
-
rescue => e
|
15
|
-
Taskinator.logger.error(e)
|
16
|
-
process.fail!(e)
|
17
|
-
raise e
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|