taskinator 0.4.7 → 0.5.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/.github/workflows/{taskinator.yml → build.yml} +2 -15
- data/.github/workflows/release.yml +18 -0
- data/CHANGELOG.md +33 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +64 -69
- data/README.md +50 -42
- data/lib/taskinator/builder.rb +129 -0
- data/lib/taskinator/definition.rb +2 -2
- data/lib/taskinator/instrumentation.rb +1 -0
- data/lib/taskinator/persistence.rb +51 -5
- data/lib/taskinator/process.rb +18 -9
- data/lib/taskinator/queues/active_job.rb +0 -12
- data/lib/taskinator/queues/delayed_job.rb +0 -11
- data/lib/taskinator/queues/resque.rb +0 -15
- data/lib/taskinator/queues/sidekiq.rb +0 -13
- data/lib/taskinator/queues.rb +0 -5
- data/lib/taskinator/task.rb +9 -11
- data/lib/taskinator/version.rb +1 -1
- data/lib/taskinator.rb +0 -14
- data/spec/support/test_job.rb +30 -0
- data/spec/support/test_job_task.rb +2 -0
- data/spec/support/test_queue.rb +21 -15
- data/spec/support/test_step_task.rb +2 -0
- data/spec/support/test_subprocess_task.rb +2 -0
- data/spec/taskinator/{definition/builder_spec.rb → builder_spec.rb} +2 -2
- data/spec/taskinator/definition_spec.rb +32 -1
- data/spec/taskinator/instrumentation_spec.rb +3 -2
- data/spec/taskinator/persistence_spec.rb +131 -5
- data/spec/taskinator/process_spec.rb +11 -3
- data/spec/taskinator/queues/active_job_spec.rb +0 -21
- data/spec/taskinator/queues/delayed_job_spec.rb +0 -18
- data/spec/taskinator/queues/resque_spec.rb +0 -21
- data/spec/taskinator/queues/sidekiq_spec.rb +0 -19
- data/spec/taskinator/queues/test_queue_adapter_spec.rb +9 -0
- data/spec/taskinator/task_spec.rb +43 -25
- data/spec/taskinator/taskinator_spec.rb +16 -0
- data/spec/taskinator/test_flows_spec.rb +16 -8
- data/taskinator.gemspec +2 -3
- metadata +21 -31
- data/lib/taskinator/definition/builder.rb +0 -129
- data/lib/taskinator/log_stats.rb +0 -49
- data/lib/taskinator/process_worker.rb +0 -13
- data/lib/taskinator/xml_visitor.rb +0 -109
- data/spec/taskinator/process_worker_spec.rb +0 -5
- data/spec/taskinator/xml_visitor_spec.rb +0 -5
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'builder'
|
2
|
+
|
1
3
|
module Taskinator
|
2
4
|
module Persistence
|
3
5
|
|
@@ -447,6 +449,46 @@ module Taskinator
|
|
447
449
|
end
|
448
450
|
end
|
449
451
|
|
452
|
+
class UnknownTypeError < StandardError
|
453
|
+
end
|
454
|
+
|
455
|
+
module UnknownType
|
456
|
+
|
457
|
+
@unknown_types = {}
|
458
|
+
|
459
|
+
def self.new(type)
|
460
|
+
Taskinator.logger.error("Unknown type '#{type}' while deserializing.")
|
461
|
+
@unknown_types[type] ||= Module.new do
|
462
|
+
extend UnknownType
|
463
|
+
@type = type
|
464
|
+
|
465
|
+
# for unknown definitions
|
466
|
+
def method_missing(_, *_)
|
467
|
+
raise UnknownTypeError.new(to_s)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
attr_reader :type
|
473
|
+
|
474
|
+
def to_s
|
475
|
+
"Unknown type '#{type}'."
|
476
|
+
end
|
477
|
+
|
478
|
+
def allocate
|
479
|
+
self
|
480
|
+
end
|
481
|
+
|
482
|
+
def accept(*_)
|
483
|
+
# nothing doing
|
484
|
+
end
|
485
|
+
|
486
|
+
# for unknown job types
|
487
|
+
def perform(*_)
|
488
|
+
raise UnknownTypeError.new(to_s)
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
450
492
|
class RedisDeserializationVisitor < Taskinator::Visitor::Base
|
451
493
|
|
452
494
|
#
|
@@ -480,7 +522,7 @@ module Taskinator
|
|
480
522
|
return unless @attribute_values.key?(:type)
|
481
523
|
|
482
524
|
type = @attribute_values[:type]
|
483
|
-
klass = Kernel.const_get(type)
|
525
|
+
klass = Kernel.const_get(type) rescue UnknownType.new(type)
|
484
526
|
|
485
527
|
#
|
486
528
|
# NOTE:
|
@@ -539,16 +581,18 @@ module Taskinator
|
|
539
581
|
def visit_attribute_enum(attribute, type)
|
540
582
|
visit_attribute(attribute) do |value|
|
541
583
|
const_value = type.constants.select {|c| type.const_get(c) == value.to_i }.first
|
542
|
-
const_value
|
543
|
-
type.const_get(const_value)
|
544
|
-
|
584
|
+
if const_value
|
585
|
+
type.const_get(const_value)
|
586
|
+
else
|
587
|
+
defined?(type::Default) ? type::Default : nil
|
588
|
+
end
|
545
589
|
end
|
546
590
|
end
|
547
591
|
|
548
592
|
def visit_type(attribute)
|
549
593
|
value = @attribute_values[attribute]
|
550
594
|
if value
|
551
|
-
type = Kernel.const_get(value)
|
595
|
+
type = Kernel.const_get(value) rescue UnknownType.new(value)
|
552
596
|
@instance.instance_variable_set("@#{attribute}", type)
|
553
597
|
end
|
554
598
|
end
|
@@ -576,6 +620,8 @@ module Taskinator
|
|
576
620
|
type = Taskinator.redis do |conn|
|
577
621
|
conn.hget(base.key_for(uuid), :type)
|
578
622
|
end
|
623
|
+
# these types are always from taskinator
|
624
|
+
# so no need to rescue for unknown types!
|
579
625
|
klass = Kernel.const_get(type)
|
580
626
|
LazyLoader.new(klass, uuid, @instance_cache)
|
581
627
|
end
|
data/lib/taskinator/process.rb
CHANGED
@@ -48,6 +48,7 @@ module Taskinator
|
|
48
48
|
@parent = value
|
49
49
|
# update the uuid to be "scoped" within the parent task
|
50
50
|
@uuid = "#{@parent.uuid}:subprocess"
|
51
|
+
@key = nil # NB: invalidate memoized key
|
51
52
|
end
|
52
53
|
|
53
54
|
def tasks
|
@@ -123,7 +124,7 @@ module Taskinator
|
|
123
124
|
instrument('taskinator.process.completed', completed_payload) do
|
124
125
|
complete if respond_to?(:complete)
|
125
126
|
# notify the parent task (if there is one) that this process has completed
|
126
|
-
# note: parent may be a proxy, so
|
127
|
+
# note: parent may be a proxy, so explicitly check for nil?
|
127
128
|
unless parent.nil?
|
128
129
|
parent.complete!
|
129
130
|
else
|
@@ -133,6 +134,9 @@ module Taskinator
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
137
|
+
# TODO: add retry method - to pick up from a failed task
|
138
|
+
# e.g. like retrying a failed job in Resque Web
|
139
|
+
|
136
140
|
def tasks_completed?
|
137
141
|
# TODO: optimize this
|
138
142
|
tasks.all?(&:completed?)
|
@@ -151,7 +155,7 @@ module Taskinator
|
|
151
155
|
instrument('taskinator.process.failed', failed_payload(error)) do
|
152
156
|
fail(error) if respond_to?(:fail)
|
153
157
|
# notify the parent task (if there is one) that this process has failed
|
154
|
-
# note: parent may be a proxy, so
|
158
|
+
# note: parent may be a proxy, so explicitly check for nil?
|
155
159
|
parent.fail!(error) unless parent.nil?
|
156
160
|
end
|
157
161
|
end
|
@@ -166,6 +170,7 @@ module Taskinator
|
|
166
170
|
# subclasses must implement the following methods
|
167
171
|
#--------------------------------------------------
|
168
172
|
|
173
|
+
# :nocov:
|
169
174
|
def enqueue
|
170
175
|
raise NotImplementedError
|
171
176
|
end
|
@@ -177,6 +182,7 @@ module Taskinator
|
|
177
182
|
def task_completed(task)
|
178
183
|
raise NotImplementedError
|
179
184
|
end
|
185
|
+
# :nocov:
|
180
186
|
|
181
187
|
#--------------------------------------------------
|
182
188
|
|
@@ -199,10 +205,9 @@ module Taskinator
|
|
199
205
|
end
|
200
206
|
|
201
207
|
def task_completed(task)
|
202
|
-
#
|
208
|
+
# decrement the count of pending sequential tasks
|
203
209
|
pending = deincr_pending_tasks
|
204
210
|
|
205
|
-
Taskinator.statsd_client.count("taskinator.#{definition.name.underscore.parameterize}.pending", pending)
|
206
211
|
Taskinator.logger.info("Completed task for process '#{uuid}'. Pending is #{pending}.")
|
207
212
|
|
208
213
|
next_task = task.next
|
@@ -222,19 +227,21 @@ module Taskinator
|
|
222
227
|
|
223
228
|
class Concurrent < Process
|
224
229
|
attr_reader :complete_on
|
230
|
+
|
231
|
+
# <b>DEPRECATED:</b> concurrency_method will be removed in a future version.
|
225
232
|
attr_reader :concurrency_method
|
226
233
|
|
227
234
|
def initialize(definition, complete_on=CompleteOn::Default, options={})
|
228
235
|
super(definition, options)
|
229
236
|
@complete_on = complete_on
|
230
237
|
@concurrency_method = options.delete(:concurrency_method) || :thread
|
238
|
+
warn("[DEPRECATED]: concurrency_method will be removed in a future version.") if @concurrency_method == :fork
|
231
239
|
end
|
232
240
|
|
233
241
|
def enqueue
|
234
242
|
if tasks.empty?
|
235
243
|
complete! # weren't any tasks to start with
|
236
244
|
else
|
237
|
-
Taskinator.statsd_client.count("taskinator.#{definition.name.underscore.parameterize}.pending", tasks.count)
|
238
245
|
Taskinator.logger.info("Enqueuing #{tasks.count} tasks for process '#{uuid}'.")
|
239
246
|
tasks.each(&:enqueue!)
|
240
247
|
end
|
@@ -246,12 +253,15 @@ module Taskinator
|
|
246
253
|
complete! # weren't any tasks to start with
|
247
254
|
else
|
248
255
|
if concurrency_method == :fork
|
256
|
+
# :nocov:
|
257
|
+
warn("[DEPRECATED]: concurrency_method will be removed in a future version.")
|
249
258
|
tasks.each do |task|
|
250
259
|
fork do
|
251
260
|
task.start!
|
252
261
|
end
|
253
262
|
end
|
254
263
|
Process.waitall
|
264
|
+
# :nocov:
|
255
265
|
else
|
256
266
|
threads = tasks.map do |task|
|
257
267
|
Thread.new do
|
@@ -264,14 +274,13 @@ module Taskinator
|
|
264
274
|
end
|
265
275
|
|
266
276
|
def task_completed(task)
|
267
|
-
#
|
277
|
+
# decrement the count of pending concurrent tasks
|
268
278
|
pending = deincr_pending_tasks
|
269
279
|
|
270
|
-
Taskinator.statsd_client.count("taskinator.#{definition.name.underscore.parameterize}.pending", pending)
|
271
280
|
Taskinator.logger.info("Completed task for process '#{uuid}'. Pending is #{pending}.")
|
272
281
|
|
273
282
|
# when complete on first, then don't bother with subsequent tasks completing
|
274
|
-
if
|
283
|
+
if complete_on == CompleteOn::First
|
275
284
|
complete! unless completed?
|
276
285
|
else
|
277
286
|
complete! if pending < 1
|
@@ -279,7 +288,7 @@ module Taskinator
|
|
279
288
|
end
|
280
289
|
|
281
290
|
def tasks_completed?
|
282
|
-
if
|
291
|
+
if complete_on == CompleteOn::First
|
283
292
|
tasks.any?(&:completed?)
|
284
293
|
else
|
285
294
|
super # all
|
@@ -18,12 +18,6 @@ module Taskinator
|
|
18
18
|
.perform_later(definition.name, uuid, Taskinator::Persistence.serialize(args))
|
19
19
|
end
|
20
20
|
|
21
|
-
def enqueue_process(process)
|
22
|
-
queue = process.queue || @config[:process_queue]
|
23
|
-
ProcessWorker.set(:queue => queue)
|
24
|
-
.perform_later(process.uuid)
|
25
|
-
end
|
26
|
-
|
27
21
|
def enqueue_task(task)
|
28
22
|
queue = task.queue || @config[:task_queue]
|
29
23
|
TaskWorker.set(:queue => queue)
|
@@ -36,12 +30,6 @@ module Taskinator
|
|
36
30
|
end
|
37
31
|
end
|
38
32
|
|
39
|
-
class ProcessWorker < ApplicationJob
|
40
|
-
def perform(process_uuid)
|
41
|
-
Taskinator::ProcessWorker.new(process_uuid).perform
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
33
|
class TaskWorker < ApplicationJob
|
46
34
|
def perform(task_uuid)
|
47
35
|
Taskinator::TaskWorker.new(task_uuid).perform
|
@@ -17,11 +17,6 @@ module Taskinator
|
|
17
17
|
::Delayed::Job.enqueue CreateProcessWorker.new(definition.name, uuid, Taskinator::Persistence.serialize(args)), :queue => queue
|
18
18
|
end
|
19
19
|
|
20
|
-
def enqueue_process(process)
|
21
|
-
queue = process.queue || @config[:process_queue]
|
22
|
-
::Delayed::Job.enqueue ProcessWorker.new(process.uuid), :queue => queue
|
23
|
-
end
|
24
|
-
|
25
20
|
def enqueue_task(task)
|
26
21
|
queue = task.queue || @config[:task_queue]
|
27
22
|
::Delayed::Job.enqueue TaskWorker.new(task.uuid), :queue => queue
|
@@ -33,12 +28,6 @@ module Taskinator
|
|
33
28
|
end
|
34
29
|
end
|
35
30
|
|
36
|
-
ProcessWorker = Struct.new(:process_uuid) do
|
37
|
-
def perform
|
38
|
-
Taskinator::ProcessWorker.new(process_uuid).perform
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
31
|
TaskWorker = Struct.new(:task_uuid) do
|
43
32
|
def perform
|
44
33
|
Taskinator::TaskWorker.new(task_uuid).perform
|
@@ -15,10 +15,6 @@ module Taskinator
|
|
15
15
|
@queue = config[:definition_queue]
|
16
16
|
end
|
17
17
|
|
18
|
-
ProcessWorker.class_eval do
|
19
|
-
@queue = config[:process_queue]
|
20
|
-
end
|
21
|
-
|
22
18
|
TaskWorker.class_eval do
|
23
19
|
@queue = config[:task_queue]
|
24
20
|
end
|
@@ -30,11 +26,6 @@ module Taskinator
|
|
30
26
|
Resque.enqueue_to(queue, CreateProcessWorker, definition.name, uuid, Taskinator::Persistence.serialize(args))
|
31
27
|
end
|
32
28
|
|
33
|
-
def enqueue_process(process)
|
34
|
-
queue = process.queue || Resque.queue_from_class(ProcessWorker)
|
35
|
-
Resque.enqueue_to(queue, ProcessWorker, process.uuid)
|
36
|
-
end
|
37
|
-
|
38
29
|
def enqueue_task(task)
|
39
30
|
queue = task.queue || Resque.queue_from_class(TaskWorker)
|
40
31
|
Resque.enqueue_to(queue, TaskWorker, task.uuid)
|
@@ -46,12 +37,6 @@ module Taskinator
|
|
46
37
|
end
|
47
38
|
end
|
48
39
|
|
49
|
-
class ProcessWorker
|
50
|
-
def self.perform(process_uuid)
|
51
|
-
Taskinator::ProcessWorker.new(process_uuid).perform
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
40
|
class TaskWorker
|
56
41
|
def self.perform(task_uuid)
|
57
42
|
Taskinator::TaskWorker.new(task_uuid).perform
|
@@ -17,11 +17,6 @@ module Taskinator
|
|
17
17
|
CreateProcessWorker.client_push('class' => CreateProcessWorker, 'args' => [definition.name, uuid, Taskinator::Persistence.serialize(args)], 'queue' => queue)
|
18
18
|
end
|
19
19
|
|
20
|
-
def enqueue_process(process)
|
21
|
-
queue = process.queue || @config[:process_queue]
|
22
|
-
TaskWorker.client_push('class' => ProcessWorker, 'args' => [process.uuid], 'queue' => queue)
|
23
|
-
end
|
24
|
-
|
25
20
|
def enqueue_task(task)
|
26
21
|
queue = task.queue || @config[:task_queue]
|
27
22
|
TaskWorker.client_push('class' => TaskWorker, 'args' => [task.uuid], 'queue' => queue)
|
@@ -35,14 +30,6 @@ module Taskinator
|
|
35
30
|
end
|
36
31
|
end
|
37
32
|
|
38
|
-
class ProcessWorker
|
39
|
-
include ::Sidekiq::Worker
|
40
|
-
|
41
|
-
def perform(process_uuid)
|
42
|
-
Taskinator::ProcessWorker.new(process_uuid).perform
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
33
|
class TaskWorker
|
47
34
|
include ::Sidekiq::Worker
|
48
35
|
|
data/lib/taskinator/queues.rb
CHANGED
@@ -33,11 +33,6 @@ module Taskinator
|
|
33
33
|
adapter.enqueue_create_process(definition, uuid, args)
|
34
34
|
end
|
35
35
|
|
36
|
-
def enqueue_process(process)
|
37
|
-
Taskinator.logger.info("Enqueuing process #{process}")
|
38
|
-
adapter.enqueue_process(process)
|
39
|
-
end
|
40
|
-
|
41
36
|
def enqueue_task(task)
|
42
37
|
Taskinator.logger.info("Enqueuing task #{task}")
|
43
38
|
adapter.enqueue_task(task)
|
data/lib/taskinator/task.rb
CHANGED
@@ -21,6 +21,7 @@ module Taskinator
|
|
21
21
|
end
|
22
22
|
|
23
23
|
attr_reader :process
|
24
|
+
attr_reader :definition
|
24
25
|
attr_reader :uuid
|
25
26
|
attr_reader :options
|
26
27
|
attr_reader :queue
|
@@ -35,6 +36,7 @@ module Taskinator
|
|
35
36
|
|
36
37
|
@uuid = "#{process.uuid}:task:#{Taskinator.generate_uuid}"
|
37
38
|
@process = process
|
39
|
+
@definition = process.definition
|
38
40
|
@options = options
|
39
41
|
@queue = options.delete(:queue)
|
40
42
|
@created_at = Time.now.utc
|
@@ -45,6 +47,7 @@ module Taskinator
|
|
45
47
|
def accept(visitor)
|
46
48
|
visitor.visit_attribute(:uuid)
|
47
49
|
visitor.visit_process_reference(:process)
|
50
|
+
visitor.visit_type(:definition)
|
48
51
|
visitor.visit_task_reference(:next)
|
49
52
|
visitor.visit_args(:options)
|
50
53
|
visitor.visit_attribute(:queue)
|
@@ -134,6 +137,7 @@ module Taskinator
|
|
134
137
|
# subclasses must implement the following methods
|
135
138
|
#--------------------------------------------------
|
136
139
|
|
140
|
+
# :nocov:
|
137
141
|
def enqueue
|
138
142
|
raise NotImplementedError
|
139
143
|
end
|
@@ -141,6 +145,7 @@ module Taskinator
|
|
141
145
|
def start
|
142
146
|
raise NotImplementedError
|
143
147
|
end
|
148
|
+
# :nocov:
|
144
149
|
|
145
150
|
#--------------------------------------------------
|
146
151
|
# and optionally, provide methods:
|
@@ -155,13 +160,11 @@ module Taskinator
|
|
155
160
|
# a task which invokes the specified method on the definition
|
156
161
|
# the args must be intrinsic types, since they are serialized to YAML
|
157
162
|
class Step < Task
|
158
|
-
attr_reader :definition
|
159
163
|
attr_reader :method
|
160
164
|
attr_reader :args
|
161
165
|
|
162
166
|
def initialize(process, method, args, options={})
|
163
167
|
super(process, options)
|
164
|
-
@definition = process.definition # for convenience
|
165
168
|
|
166
169
|
raise ArgumentError, 'method' if method.nil?
|
167
170
|
raise NoMethodError, method unless executor.respond_to?(method)
|
@@ -188,17 +191,16 @@ module Taskinator
|
|
188
191
|
|
189
192
|
def accept(visitor)
|
190
193
|
super
|
191
|
-
visitor.visit_type(:definition)
|
192
194
|
visitor.visit_attribute(:method)
|
193
195
|
visitor.visit_args(:args)
|
194
196
|
end
|
195
197
|
|
196
198
|
def executor
|
197
|
-
@executor ||= Taskinator::Executor.new(
|
199
|
+
@executor ||= Taskinator::Executor.new(definition, self)
|
198
200
|
end
|
199
201
|
|
200
202
|
def inspect
|
201
|
-
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", method=:#{method}, args=#{args}, current_state=:#{current_state}>)
|
203
|
+
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", definition=:#{definition}, method=:#{method}, args=#{args}, current_state=:#{current_state}>)
|
202
204
|
end
|
203
205
|
end
|
204
206
|
|
@@ -207,13 +209,11 @@ module Taskinator
|
|
207
209
|
# a task which invokes the specified background job
|
208
210
|
# the args must be intrinsic types, since they are serialized to YAML
|
209
211
|
class Job < Task
|
210
|
-
attr_reader :definition
|
211
212
|
attr_reader :job
|
212
213
|
attr_reader :args
|
213
214
|
|
214
215
|
def initialize(process, job, args, options={})
|
215
216
|
super(process, options)
|
216
|
-
@definition = process.definition # for convenience
|
217
217
|
|
218
218
|
raise ArgumentError, 'job' if job.nil?
|
219
219
|
raise ArgumentError, 'job' unless job.methods.include?(:perform) || job.instance_methods.include?(:perform)
|
@@ -228,7 +228,6 @@ module Taskinator
|
|
228
228
|
|
229
229
|
def start
|
230
230
|
# NNB: if other job types are required, may need to implement how they get invoked here!
|
231
|
-
# FIXME: possible implement using ActiveJob instead, so it doesn't matter how the worker is implemented
|
232
231
|
|
233
232
|
if job.respond_to?(:perform)
|
234
233
|
# resque
|
@@ -250,13 +249,12 @@ module Taskinator
|
|
250
249
|
|
251
250
|
def accept(visitor)
|
252
251
|
super
|
253
|
-
visitor.visit_type(:definition)
|
254
252
|
visitor.visit_type(:job)
|
255
253
|
visitor.visit_args(:args)
|
256
254
|
end
|
257
255
|
|
258
256
|
def inspect
|
259
|
-
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", job=#{job}, args=#{args}, current_state=:#{current_state}>)
|
257
|
+
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", definition=:#{definition}, job=#{job}, args=#{args}, current_state=:#{current_state}>)
|
260
258
|
end
|
261
259
|
end
|
262
260
|
|
@@ -302,7 +300,7 @@ module Taskinator
|
|
302
300
|
end
|
303
301
|
|
304
302
|
def inspect
|
305
|
-
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", sub_process=#{sub_process.inspect}, current_state=:#{current_state}>)
|
303
|
+
%(#<#{self.class.name}:0x#{self.__id__.to_s(16)} uuid="#{uuid}", definition=:#{definition}, sub_process=#{sub_process.inspect}, current_state=:#{current_state}>)
|
306
304
|
end
|
307
305
|
end
|
308
306
|
end
|
data/lib/taskinator/version.rb
CHANGED
data/lib/taskinator.rb
CHANGED
@@ -6,8 +6,6 @@ require 'delegate'
|
|
6
6
|
|
7
7
|
require 'taskinator/version'
|
8
8
|
|
9
|
-
require 'taskinator/log_stats'
|
10
|
-
|
11
9
|
require 'taskinator/complete_on'
|
12
10
|
require 'taskinator/redis_connection'
|
13
11
|
require 'taskinator/logger'
|
@@ -19,14 +17,12 @@ require 'taskinator/workflow'
|
|
19
17
|
require 'taskinator/visitor'
|
20
18
|
require 'taskinator/persistence'
|
21
19
|
require 'taskinator/instrumentation'
|
22
|
-
require 'taskinator/xml_visitor'
|
23
20
|
|
24
21
|
require 'taskinator/task'
|
25
22
|
require 'taskinator/tasks'
|
26
23
|
require 'taskinator/process'
|
27
24
|
|
28
25
|
require 'taskinator/task_worker'
|
29
|
-
require 'taskinator/process_worker'
|
30
26
|
require 'taskinator/create_process_worker'
|
31
27
|
|
32
28
|
require 'taskinator/executor'
|
@@ -88,14 +84,6 @@ module Taskinator
|
|
88
84
|
Taskinator::Logging.logger = log
|
89
85
|
end
|
90
86
|
|
91
|
-
def statsd_client
|
92
|
-
Taskinator::LogStats.client
|
93
|
-
end
|
94
|
-
|
95
|
-
def statsd_client=(client)
|
96
|
-
Taskinator::LogStats.client = client
|
97
|
-
end
|
98
|
-
|
99
87
|
# the queue adapter to use
|
100
88
|
# supported adapters include
|
101
89
|
# :active_job, :delayed_job, :redis and :sidekiq
|
@@ -136,14 +124,12 @@ module Taskinator
|
|
136
124
|
end
|
137
125
|
|
138
126
|
class NoOpInstrumenter
|
139
|
-
# :nocov:
|
140
127
|
def instrument(event, payload={})
|
141
128
|
yield(payload) if block_given?
|
142
129
|
end
|
143
130
|
end
|
144
131
|
|
145
132
|
class ConsoleInstrumenter
|
146
|
-
# :nocov:
|
147
133
|
def instrument(event, payload={})
|
148
134
|
puts [event.inspect, payload.to_yaml]
|
149
135
|
yield(payload) if block_given?
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module TestJob
|
2
|
+
def self.perform(*args)
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
class TestJobClass
|
7
|
+
def perform(*args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module TestJobModule
|
12
|
+
def self.perform(*args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestJobClassNoArgs
|
17
|
+
def perform
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module TestJobModuleNoArgs
|
22
|
+
def self.perform
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module TestJobError
|
27
|
+
def self.perform
|
28
|
+
raise ArgumentError
|
29
|
+
end
|
30
|
+
end
|
data/spec/support/test_queue.rb
CHANGED
@@ -2,38 +2,42 @@ module Taskinator
|
|
2
2
|
module Queues
|
3
3
|
|
4
4
|
def self.create_test_queue_adapter(config={})
|
5
|
-
TestQueueAdapter.new
|
5
|
+
TestQueueAdapter.new(config)
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.create_test_queue_worker_adapter(config={})
|
9
|
-
|
9
|
+
TestQueueWorkerAdapter.new(config)
|
10
10
|
end
|
11
11
|
|
12
|
+
#
|
13
|
+
# this is a no-op adapter, it tracks enqueued processes and tasks
|
14
|
+
#
|
12
15
|
class TestQueueAdapter
|
13
16
|
|
14
|
-
|
15
|
-
attr_reader :tasks
|
16
|
-
|
17
|
-
def initialize
|
17
|
+
def initialize(config={})
|
18
18
|
clear
|
19
19
|
end
|
20
20
|
|
21
|
-
def clear
|
22
|
-
@creates = []
|
23
|
-
@tasks = []
|
24
|
-
@jobs = []
|
25
|
-
end
|
26
|
-
|
27
21
|
def enqueue_create_process(definition, uuid, args)
|
28
|
-
@
|
22
|
+
@processes << [definition, uuid, args]
|
29
23
|
end
|
30
24
|
|
31
25
|
def enqueue_task(task)
|
32
26
|
@tasks << task
|
33
27
|
end
|
34
28
|
|
29
|
+
# helpers
|
30
|
+
|
31
|
+
attr_reader :processes
|
32
|
+
attr_reader :tasks
|
33
|
+
|
34
|
+
def clear
|
35
|
+
@processes = []
|
36
|
+
@tasks = []
|
37
|
+
end
|
38
|
+
|
35
39
|
def empty?
|
36
|
-
@
|
40
|
+
@processes.empty? && @tasks.empty?
|
37
41
|
end
|
38
42
|
|
39
43
|
end
|
@@ -41,7 +45,7 @@ module Taskinator
|
|
41
45
|
#
|
42
46
|
# this is a "synchronous" implementation for use in testing
|
43
47
|
#
|
44
|
-
class
|
48
|
+
class TestQueueWorkerAdapter < TestQueueAdapter
|
45
49
|
|
46
50
|
def enqueue_create_process(definition, uuid, args)
|
47
51
|
super
|
@@ -57,6 +61,8 @@ module Taskinator
|
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
64
|
+
private
|
65
|
+
|
60
66
|
def invoke(&block)
|
61
67
|
block.call
|
62
68
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Taskinator::
|
3
|
+
describe Taskinator::Builder do
|
4
4
|
|
5
5
|
let(:definition) do
|
6
6
|
Module.new do
|
@@ -26,7 +26,7 @@ describe Taskinator::Definition::Builder do
|
|
26
26
|
Proc.new {|*args| the_block.call }
|
27
27
|
}
|
28
28
|
|
29
|
-
subject { Taskinator::
|
29
|
+
subject { Taskinator::Builder.new(process, definition, *[*args, builder_options]) }
|
30
30
|
|
31
31
|
it "assign attributes" do
|
32
32
|
expect(subject.process).to eq(process)
|