cloudtasker 0.1.0 → 0.6.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +10 -1
- data/Appraisals +25 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +37 -4
- data/README.md +573 -6
- data/Rakefile +6 -0
- data/app/controllers/cloudtasker/application_controller.rb +2 -0
- data/app/controllers/cloudtasker/worker_controller.rb +24 -2
- data/cloudtasker.gemspec +7 -3
- data/docs/BATCH_JOBS.md +66 -0
- data/docs/CRON_JOBS.md +63 -0
- data/docs/UNIQUE_JOBS.md +127 -0
- data/exe/cloudtasker +15 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/google_cloud_tasks_1.0.gemfile +9 -0
- data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +263 -0
- data/gemfiles/google_cloud_tasks_1.1.gemfile +9 -0
- data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +263 -0
- data/gemfiles/google_cloud_tasks_1.2.gemfile +9 -0
- data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +263 -0
- data/gemfiles/google_cloud_tasks_1.3.gemfile +9 -0
- data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +264 -0
- data/gemfiles/rails_4.0.gemfile +10 -0
- data/gemfiles/rails_4.1.gemfile +9 -0
- data/gemfiles/rails_4.2.gemfile +9 -0
- data/gemfiles/rails_5.0.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +9 -0
- data/gemfiles/rails_5.2.gemfile +9 -0
- data/gemfiles/rails_5.2.gemfile.lock +247 -0
- data/gemfiles/rails_6.0.gemfile +9 -0
- data/gemfiles/rails_6.0.gemfile.lock +263 -0
- data/lib/cloudtasker.rb +21 -1
- data/lib/cloudtasker/backend/google_cloud_task.rb +139 -0
- data/lib/cloudtasker/backend/memory_task.rb +190 -0
- data/lib/cloudtasker/backend/redis_task.rb +249 -0
- data/lib/cloudtasker/batch/batch_progress.rb +19 -1
- data/lib/cloudtasker/batch/job.rb +88 -23
- data/lib/cloudtasker/batch/middleware.rb +0 -1
- data/lib/cloudtasker/cli.rb +194 -0
- data/lib/cloudtasker/cloud_task.rb +91 -0
- data/lib/cloudtasker/config.rb +64 -2
- data/lib/cloudtasker/cron/job.rb +6 -3
- data/lib/cloudtasker/cron/middleware.rb +0 -1
- data/lib/cloudtasker/cron/schedule.rb +73 -13
- data/lib/cloudtasker/dead_worker_error.rb +6 -0
- data/lib/cloudtasker/local_server.rb +74 -0
- data/lib/cloudtasker/railtie.rb +10 -0
- data/lib/cloudtasker/redis_client.rb +24 -2
- data/lib/cloudtasker/testing.rb +133 -0
- data/lib/cloudtasker/unique_job/job.rb +5 -2
- data/lib/cloudtasker/unique_job/lock/base_lock.rb +1 -1
- data/lib/cloudtasker/unique_job/lock/until_executed.rb +3 -1
- data/lib/cloudtasker/unique_job/lock/while_executing.rb +3 -1
- data/lib/cloudtasker/unique_job/middleware.rb +0 -1
- data/lib/cloudtasker/version.rb +1 -1
- data/lib/cloudtasker/worker.rb +59 -16
- data/lib/cloudtasker/{task.rb → worker_handler.rb} +10 -77
- data/lib/cloudtasker/worker_logger.rb +155 -0
- data/lib/tasks/setup_queue.rake +10 -0
- metadata +98 -9
- data/lib/cloudtasker/batch/config.rb +0 -11
- data/lib/cloudtasker/cron/config.rb +0 -11
- data/lib/cloudtasker/unique_job/config.rb +0 -10
data/lib/cloudtasker/config.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'logger'
|
4
|
+
|
3
5
|
module Cloudtasker
|
4
6
|
# Holds cloudtasker configuration. See Cloudtasker#configure
|
5
7
|
class Config
|
6
8
|
attr_accessor :redis
|
7
9
|
attr_writer :secret, :gcp_location_id, :gcp_project_id,
|
8
|
-
:gcp_queue_id, :
|
10
|
+
:gcp_queue_id, :processor_path, :logger, :mode, :max_retries
|
11
|
+
|
12
|
+
# Retry header in Cloud Task responses
|
13
|
+
RETRY_HEADER = 'X-CloudTasks-TaskExecutionCount'
|
9
14
|
|
15
|
+
# Default values
|
10
16
|
DEFAULT_LOCATION_ID = 'us-east1'
|
11
17
|
DEFAULT_PROCESSOR_PATH = '/cloudtasker/run'
|
12
18
|
|
19
|
+
# The number of times jobs will be attempted before declaring them dead
|
20
|
+
DEFAULT_MAX_RETRY_ATTEMPTS = 25
|
21
|
+
|
13
22
|
PROCESSOR_HOST_MISSING = <<~DOC
|
14
23
|
Missing host for processing.
|
15
24
|
Please specify a processor hostname in form of `https://some-public-dns.example.com`'
|
@@ -27,6 +36,46 @@ module Cloudtasker
|
|
27
36
|
Please specify a secret in the cloudtasker initializer or add Rails secret_key_base in your credentials
|
28
37
|
DOC
|
29
38
|
|
39
|
+
#
|
40
|
+
# The number of times jobs will be retried. This number of
|
41
|
+
# retries does not include failures due to the application being unreachable.
|
42
|
+
#
|
43
|
+
#
|
44
|
+
# @return [Integer] The number of retries
|
45
|
+
#
|
46
|
+
def max_retries
|
47
|
+
@max_retries ||= DEFAULT_MAX_RETRY_ATTEMPTS
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# The operating mode.
|
52
|
+
# - :production => process tasks via GCP Cloud Task.
|
53
|
+
# - :development => process tasks locally via Redis.
|
54
|
+
#
|
55
|
+
# @return [<Type>] <description>
|
56
|
+
#
|
57
|
+
def mode
|
58
|
+
@mode ||= environment == 'development' ? :development : :production
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Return the current environment.
|
63
|
+
#
|
64
|
+
# @return [String] The environment name.
|
65
|
+
#
|
66
|
+
def environment
|
67
|
+
ENV['CLOUDTASKER_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Return the Cloudtasker logger.
|
72
|
+
#
|
73
|
+
# @return [Logger, any] The cloudtasker logger.
|
74
|
+
#
|
75
|
+
def logger
|
76
|
+
@logger ||= defined?(Rails) ? Rails.logger : ::Logger.new(STDOUT)
|
77
|
+
end
|
78
|
+
|
30
79
|
#
|
31
80
|
# Return the full URL of the processor. Worker payloads will be sent
|
32
81
|
# to this URL.
|
@@ -37,6 +86,19 @@ module Cloudtasker
|
|
37
86
|
File.join(processor_host, processor_path)
|
38
87
|
end
|
39
88
|
|
89
|
+
#
|
90
|
+
# Set the processor host. In the context of Rails the host will
|
91
|
+
# also be added to the list of authorized Rails hosts.
|
92
|
+
#
|
93
|
+
# @param [String] val The processor host to set.
|
94
|
+
#
|
95
|
+
def processor_host=(val)
|
96
|
+
@processor_host = val
|
97
|
+
|
98
|
+
# Add processor host to the list of authorized hosts
|
99
|
+
Rails.application.config.hosts << val.gsub(%r{https?://}, '') if val && defined?(Rails)
|
100
|
+
end
|
101
|
+
|
40
102
|
#
|
41
103
|
# The hostname of the application processing the workers. The hostname must
|
42
104
|
# be reachable from Cloud Task.
|
@@ -93,7 +155,7 @@ module Cloudtasker
|
|
93
155
|
#
|
94
156
|
def secret
|
95
157
|
@secret || (
|
96
|
-
defined?(Rails) && Rails.application.credentials&.secret_key_base
|
158
|
+
defined?(Rails) && Rails.application.credentials&.dig(:secret_key_base)
|
97
159
|
) || raise(StandardError, SECRET_MISSING_ERROR)
|
98
160
|
end
|
99
161
|
|
data/lib/cloudtasker/cron/job.rb
CHANGED
@@ -10,6 +10,9 @@ module Cloudtasker
|
|
10
10
|
class Job
|
11
11
|
attr_reader :worker
|
12
12
|
|
13
|
+
# Key Namespace used for object saved under this class
|
14
|
+
SUB_NAMESPACE = 'job'
|
15
|
+
|
13
16
|
#
|
14
17
|
# Build a new instance of the class
|
15
18
|
#
|
@@ -29,7 +32,7 @@ module Cloudtasker
|
|
29
32
|
def key(val)
|
30
33
|
return nil if val.nil?
|
31
34
|
|
32
|
-
[
|
35
|
+
[self.class.to_s.underscore, val.to_s].join('/')
|
33
36
|
end
|
34
37
|
|
35
38
|
#
|
@@ -176,8 +179,8 @@ module Cloudtasker
|
|
176
179
|
next_worker = worker.new_instance.tap { |e| e.job_meta.set(key(:time_at), next_time.iso8601) }
|
177
180
|
|
178
181
|
# Schedule next worker
|
179
|
-
|
180
|
-
cron_schedule.update(task_id:
|
182
|
+
task = next_worker.schedule(time_at: next_time)
|
183
|
+
cron_schedule.update(task_id: task.id, job_id: next_worker.job_id)
|
181
184
|
end
|
182
185
|
|
183
186
|
#
|
@@ -8,6 +8,9 @@ module Cloudtasker
|
|
8
8
|
class Schedule
|
9
9
|
attr_accessor :id, :cron, :worker, :task_id, :job_id
|
10
10
|
|
11
|
+
# Key Namespace used for object saved under this class
|
12
|
+
SUB_NAMESPACE = 'schedule'
|
13
|
+
|
11
14
|
#
|
12
15
|
# Return the redis client.
|
13
16
|
#
|
@@ -17,6 +20,50 @@ module Cloudtasker
|
|
17
20
|
RedisClient
|
18
21
|
end
|
19
22
|
|
23
|
+
#
|
24
|
+
# Return a namespaced key.
|
25
|
+
#
|
26
|
+
# @param [String, Symbol] val The key to namespace
|
27
|
+
#
|
28
|
+
# @return [String] The namespaced key.
|
29
|
+
#
|
30
|
+
def self.key(val)
|
31
|
+
return nil if val.nil?
|
32
|
+
|
33
|
+
[to_s.underscore, val.to_s].join('/')
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Return all schedules
|
38
|
+
#
|
39
|
+
# @return [Array<Cloudtasker::Batch::Schedule>] The list of stored schedules.
|
40
|
+
#
|
41
|
+
def self.all
|
42
|
+
redis.search(key('*')).map do |gid|
|
43
|
+
find(gid.sub(key(''), ''))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Synchronize list of cron schedules from a Hash. Schedules
|
49
|
+
# not listed in this hash will be removed.
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# Cloudtasker::Cron::Schedule.load_from_hash!(
|
53
|
+
# my_job: { cron: '0 0 * * *', worker: 'MyWorker' }
|
54
|
+
# my_other_job: { cron: '0 10 * * *', worker: 'MyOtherWorker' }
|
55
|
+
# )
|
56
|
+
#
|
57
|
+
def self.load_from_hash!(hash)
|
58
|
+
schedules = hash.map do |id, config|
|
59
|
+
schedule_config = JSON.parse(config.to_json, symbolize_names: true).merge(id: id.to_s)
|
60
|
+
create(schedule_config)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Remove existing schedules which are not part of the list
|
64
|
+
all.reject { |e| schedules.include?(e) }.each { |e| delete(e.id) }
|
65
|
+
end
|
66
|
+
|
20
67
|
#
|
21
68
|
# Create a new cron schedule (or update an existing one).
|
22
69
|
#
|
@@ -25,8 +72,10 @@ module Cloudtasker
|
|
25
72
|
# @return [Cloudtasker::Cron::Schedule] The schedule instance.
|
26
73
|
#
|
27
74
|
def self.create(**opts)
|
28
|
-
|
29
|
-
|
75
|
+
redis.with_lock(key(opts[:id])) do
|
76
|
+
config = find(opts[:id]).to_h.merge(opts)
|
77
|
+
new(config).tap(&:save)
|
78
|
+
end
|
30
79
|
end
|
31
80
|
|
32
81
|
#
|
@@ -37,8 +86,7 @@ module Cloudtasker
|
|
37
86
|
# @return [Cloudtasker::Cron::Schedule] The schedule instance.
|
38
87
|
#
|
39
88
|
def self.find(id)
|
40
|
-
|
41
|
-
return nil unless (schedule_config = redis.fetch(gid))
|
89
|
+
return nil unless (schedule_config = redis.fetch(key(id)))
|
42
90
|
|
43
91
|
new(schedule_config)
|
44
92
|
end
|
@@ -49,12 +97,14 @@ module Cloudtasker
|
|
49
97
|
# @param [String] id The schedule id.
|
50
98
|
#
|
51
99
|
def self.delete(id)
|
52
|
-
|
53
|
-
|
100
|
+
redis.with_lock(key(id)) do
|
101
|
+
schedule = find(id)
|
102
|
+
return false unless schedule
|
54
103
|
|
55
|
-
|
56
|
-
|
57
|
-
|
104
|
+
# Delete task and stored schedule
|
105
|
+
CloudTask.delete(schedule.task_id) if schedule.task_id
|
106
|
+
redis.del(schedule.gid)
|
107
|
+
end
|
58
108
|
end
|
59
109
|
|
60
110
|
#
|
@@ -89,7 +139,7 @@ module Cloudtasker
|
|
89
139
|
# @return [String] The namespaced schedule id.
|
90
140
|
#
|
91
141
|
def gid
|
92
|
-
|
142
|
+
self.class.key(id)
|
93
143
|
end
|
94
144
|
|
95
145
|
#
|
@@ -206,17 +256,27 @@ module Cloudtasker
|
|
206
256
|
# then any existing cloud task is removed and a task is recreated.
|
207
257
|
#
|
208
258
|
def save(update_task: true)
|
209
|
-
return false unless valid?
|
259
|
+
return false unless valid?
|
210
260
|
|
211
261
|
# Save schedule
|
212
262
|
config_was_changed = config_changed?
|
213
263
|
redis.write(gid, to_h)
|
214
264
|
|
215
265
|
# Stop there if backend does not need update
|
216
|
-
return true unless update_task && config_was_changed
|
266
|
+
return true unless update_task && (config_was_changed || !task_id || !CloudTask.find(task_id))
|
267
|
+
|
268
|
+
# Update backend
|
269
|
+
persist_cloud_task
|
270
|
+
end
|
217
271
|
|
272
|
+
private
|
273
|
+
|
274
|
+
#
|
275
|
+
# Update the task in backend.
|
276
|
+
#
|
277
|
+
def persist_cloud_task
|
218
278
|
# Delete previous instance
|
219
|
-
|
279
|
+
CloudTask.delete(task_id) if task_id
|
220
280
|
|
221
281
|
# Schedule worker
|
222
282
|
worker_instance = Object.const_get(worker).new
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cloudtasker/backend/redis_task'
|
4
|
+
|
5
|
+
module Cloudtasker
|
6
|
+
# Process jobs stored in Redis.
|
7
|
+
# Only to be used in development.
|
8
|
+
class LocalServer
|
9
|
+
# Max number of task requests sent to the processing server
|
10
|
+
CONCURRENCY = (ENV['CLOUDTASKER_CONCURRENCY'] || 5).to_i
|
11
|
+
|
12
|
+
#
|
13
|
+
# Stop the local server.
|
14
|
+
#
|
15
|
+
def stop
|
16
|
+
@done = true
|
17
|
+
|
18
|
+
# Terminate threads and repush tasks
|
19
|
+
@threads&.each do |t|
|
20
|
+
t.terminate
|
21
|
+
t['task']&.retry_later(0, is_error: false)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Wait for main server to be done
|
25
|
+
sleep 1 while @start&.alive?
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Start the local server
|
30
|
+
#
|
31
|
+
#
|
32
|
+
def start
|
33
|
+
@start ||= Thread.new do
|
34
|
+
until @done
|
35
|
+
process_jobs
|
36
|
+
sleep 1
|
37
|
+
end
|
38
|
+
Cloudtasker.logger.info('[Cloudtasker/Server] Local server exiting...')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Process enqueued workers.
|
44
|
+
#
|
45
|
+
#
|
46
|
+
def process_jobs
|
47
|
+
@threads ||= []
|
48
|
+
|
49
|
+
# Remove any done thread
|
50
|
+
@threads.select!(&:alive?)
|
51
|
+
|
52
|
+
# Process tasks
|
53
|
+
while @threads.count < CONCURRENCY && (task = Cloudtasker::Backend::RedisTask.pop)
|
54
|
+
@threads << Thread.new do
|
55
|
+
Thread.current['task'] = task
|
56
|
+
Thread.current['attempts'] = 0
|
57
|
+
|
58
|
+
# Deliver task
|
59
|
+
begin
|
60
|
+
Thread.current['task'].deliver
|
61
|
+
rescue Errno::ECONNREFUSED => e
|
62
|
+
raise(e) unless Thread.current['attempts'] < 3
|
63
|
+
|
64
|
+
# Retry on connection error, in case the web server is not
|
65
|
+
# started yet.
|
66
|
+
Thread.current['attempts'] += 1
|
67
|
+
sleep(3)
|
68
|
+
retry
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -8,7 +8,7 @@ module Cloudtasker
|
|
8
8
|
module_function
|
9
9
|
|
10
10
|
# Suffix added to cache keys when locking them
|
11
|
-
|
11
|
+
LOCK_KEY_PREFIX = 'cloudtasker/lock'
|
12
12
|
|
13
13
|
#
|
14
14
|
# Return the underlying redis client.
|
@@ -61,7 +61,7 @@ module Cloudtasker
|
|
61
61
|
return nil unless cache_key
|
62
62
|
|
63
63
|
# Wait to acquire lock
|
64
|
-
lock_key = [
|
64
|
+
lock_key = [LOCK_KEY_PREFIX, cache_key].join('/')
|
65
65
|
true until client.setnx(lock_key, true)
|
66
66
|
|
67
67
|
# yield content
|
@@ -83,6 +83,28 @@ module Cloudtasker
|
|
83
83
|
del(*all_keys)
|
84
84
|
end
|
85
85
|
|
86
|
+
#
|
87
|
+
# Return all keys matching the provided patterns.
|
88
|
+
#
|
89
|
+
# @param [String] pattern A redis compatible pattern.
|
90
|
+
#
|
91
|
+
# @return [Array<String>] The list of matching keys
|
92
|
+
#
|
93
|
+
def search(pattern)
|
94
|
+
# Initialize loop variables
|
95
|
+
cursor = nil
|
96
|
+
list = []
|
97
|
+
|
98
|
+
# Scan and capture matching keys
|
99
|
+
while cursor != 0
|
100
|
+
scan = client.scan(cursor || 0, match: pattern)
|
101
|
+
list += scan[1]
|
102
|
+
cursor = scan[0].to_i
|
103
|
+
end
|
104
|
+
|
105
|
+
list
|
106
|
+
end
|
107
|
+
|
86
108
|
#
|
87
109
|
# Delegate all methods to the redis client.
|
88
110
|
#
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cloudtasker/backend/memory_task'
|
4
|
+
|
5
|
+
module Cloudtasker
|
6
|
+
# Enable/Disable test mode for Cloudtasker
|
7
|
+
module Testing
|
8
|
+
module_function
|
9
|
+
|
10
|
+
#
|
11
|
+
# Set the test mode, either permanently or
|
12
|
+
# temporarily (via block).
|
13
|
+
#
|
14
|
+
# @param [Symbol] mode The test mode.
|
15
|
+
#
|
16
|
+
# @return [Symbol] The test mode.
|
17
|
+
#
|
18
|
+
def switch_test_mode(mode)
|
19
|
+
if block_given?
|
20
|
+
current_mode = @test_mode
|
21
|
+
begin
|
22
|
+
@test_mode = mode
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
@test_mode = current_mode
|
26
|
+
end
|
27
|
+
else
|
28
|
+
@test_mode = mode
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Set cloudtasker to real mode temporarily
|
34
|
+
#
|
35
|
+
# @param [Proc] &block The block to run in real mode
|
36
|
+
#
|
37
|
+
def enable!(&block)
|
38
|
+
switch_test_mode(:enabled, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Set cloudtasker to fake mode temporarily
|
43
|
+
#
|
44
|
+
# @param [Proc] &block The block to run in fake mode
|
45
|
+
#
|
46
|
+
def fake!(&block)
|
47
|
+
switch_test_mode(:fake, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Set cloudtasker to inline mode temporarily
|
52
|
+
#
|
53
|
+
# @param [Proc] &block The block to run in inline mode
|
54
|
+
#
|
55
|
+
def inline!(&block)
|
56
|
+
switch_test_mode(:inline, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Return true if Cloudtasker is enabled.
|
61
|
+
#
|
62
|
+
def enabled?
|
63
|
+
!@test_mode || @test_mode == :enabled
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Return true if Cloudtasker is in fake mode.
|
68
|
+
#
|
69
|
+
# @return [Boolean] True if jobs must be processed through drain calls.
|
70
|
+
#
|
71
|
+
def fake?
|
72
|
+
@test_mode == :fake
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Return true if Cloudtasker is in inline mode.
|
77
|
+
#
|
78
|
+
# @return [Boolean] True if jobs are run inline.
|
79
|
+
#
|
80
|
+
def inline?
|
81
|
+
@test_mode == :inline
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Return true if tasks should be managed in memory.
|
86
|
+
#
|
87
|
+
# @return [Boolean] True if jobs are managed in memory.
|
88
|
+
#
|
89
|
+
def in_memory?
|
90
|
+
!enabled?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add extra methods for testing purpose
|
95
|
+
module Worker
|
96
|
+
#
|
97
|
+
# Clear all jobs.
|
98
|
+
#
|
99
|
+
def self.clear_all
|
100
|
+
Backend::MemoryTask.clear
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Run all the jobs.
|
105
|
+
#
|
106
|
+
# @return [Array<any>] The return values of the workers perform method.
|
107
|
+
#
|
108
|
+
def self.drain_all
|
109
|
+
Backend::MemoryTask.drain
|
110
|
+
end
|
111
|
+
|
112
|
+
# Module class methods
|
113
|
+
module ClassMethods
|
114
|
+
#
|
115
|
+
# Return all jobs related to this worker class.
|
116
|
+
#
|
117
|
+
# @return [Array<Cloudtasker::Worker] The list of workers
|
118
|
+
#
|
119
|
+
def jobs
|
120
|
+
Backend::MemoryTask.jobs(to_s)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Run all jobs related to this worker class.
|
125
|
+
#
|
126
|
+
# @return [Array<any>] The return values of the workers perform method.
|
127
|
+
#
|
128
|
+
def drain
|
129
|
+
Backend::MemoryTask.drain(to_s)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|