cloudtasker 0.12.2 → 0.13.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/.github/workflows/lint_rubocop.yml +20 -0
- data/.github/workflows/{test.yml → test_ruby_2.5_2.6.yml} +11 -8
- data/.github/workflows/test_ruby_2.7.yml +44 -0
- data/.github/workflows/test_ruby_3.x.yml +43 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/Appraisals +52 -8
- data/CHANGELOG.md +10 -0
- data/README.md +14 -3
- data/Rakefile +0 -6
- data/cloudtasker.gemspec +1 -6
- data/docs/CRON_JOBS.md +2 -2
- data/gemfiles/google_cloud_tasks_1.0.gemfile +2 -1
- data/gemfiles/google_cloud_tasks_1.1.gemfile +2 -1
- data/gemfiles/google_cloud_tasks_1.2.gemfile +2 -1
- data/gemfiles/google_cloud_tasks_1.3.gemfile +2 -1
- data/gemfiles/google_cloud_tasks_1.4.gemfile +8 -0
- data/gemfiles/google_cloud_tasks_1.5.gemfile +8 -0
- data/gemfiles/google_cloud_tasks_2.0.gemfile +8 -0
- data/gemfiles/google_cloud_tasks_2.1.gemfile +8 -0
- data/gemfiles/rails_5.2.gemfile +1 -0
- data/gemfiles/rails_6.0.gemfile +1 -0
- data/gemfiles/{semantic_logger_4.7.gemfile → rails_6.1.gemfile} +2 -1
- data/gemfiles/rails_7.0.gemfile +8 -0
- data/gemfiles/semantic_logger_3.4.gemfile +1 -0
- data/gemfiles/semantic_logger_4.6.gemfile +1 -0
- data/gemfiles/semantic_logger_4.7.0.gemfile +1 -0
- data/gemfiles/semantic_logger_4.7.2.gemfile +1 -0
- data/lib/cloudtasker/backend/{google_cloud_task.rb → google_cloud_task_v1.rb} +15 -11
- data/lib/cloudtasker/backend/google_cloud_task_v2.rb +210 -0
- data/lib/cloudtasker/backend/memory_task.rb +1 -1
- data/lib/cloudtasker/backend/redis_task.rb +7 -3
- data/lib/cloudtasker/cloud_task.rb +43 -5
- data/lib/cloudtasker/cron/schedule.rb +7 -7
- data/lib/cloudtasker/redis_client.rb +39 -14
- data/lib/cloudtasker/unique_job/job.rb +3 -2
- data/lib/cloudtasker/unique_job/middleware/client.rb +2 -1
- data/lib/cloudtasker/version.rb +1 -1
- data/lib/cloudtasker/worker.rb +3 -3
- data/lib/cloudtasker/worker_wrapper.rb +1 -1
- data/lib/tasks/setup_queue.rake +2 -2
- metadata +19 -77
- data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +0 -342
- data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +0 -342
- data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +0 -342
- data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +0 -343
- data/gemfiles/rails_4.0.gemfile +0 -10
- data/gemfiles/rails_4.1.gemfile +0 -9
- data/gemfiles/rails_4.2.gemfile +0 -9
- data/gemfiles/rails_5.0.gemfile +0 -9
- data/gemfiles/rails_5.1.gemfile +0 -9
- data/gemfiles/rails_5.2.gemfile.lock +0 -327
- data/gemfiles/rails_6.0.gemfile.lock +0 -343
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'google/cloud/tasks'
|
|
4
|
+
require 'google/protobuf/timestamp_pb'
|
|
5
|
+
require 'retriable'
|
|
6
|
+
|
|
7
|
+
module Cloudtasker
|
|
8
|
+
module Backend
|
|
9
|
+
# Manage tasks pushed to GCP Cloud Task
|
|
10
|
+
class GoogleCloudTaskV2
|
|
11
|
+
attr_accessor :gcp_task
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# Create the queue configured in Cloudtasker if it does not already exist.
|
|
15
|
+
#
|
|
16
|
+
# @param [String] :name The queue name
|
|
17
|
+
# @param [Integer] :concurrency The queue concurrency
|
|
18
|
+
# @param [Integer] :retries The number of retries for the queue
|
|
19
|
+
#
|
|
20
|
+
# @return [Google::Cloud::Tasks::V2::Queue] The queue
|
|
21
|
+
#
|
|
22
|
+
def self.setup_queue(name: nil, concurrency: nil, retries: nil)
|
|
23
|
+
# Build full queue path
|
|
24
|
+
queue_name = name || Cloudtasker::Config::DEFAULT_JOB_QUEUE
|
|
25
|
+
full_queue_name = queue_path(queue_name)
|
|
26
|
+
|
|
27
|
+
# Try to get existing queue
|
|
28
|
+
client.get_queue(name: full_queue_name)
|
|
29
|
+
rescue Google::Cloud::NotFoundError
|
|
30
|
+
# Extract options
|
|
31
|
+
queue_concurrency = (concurrency || Cloudtasker::Config::DEFAULT_QUEUE_CONCURRENCY).to_i
|
|
32
|
+
queue_retries = (retries || Cloudtasker::Config::DEFAULT_QUEUE_RETRIES).to_i
|
|
33
|
+
|
|
34
|
+
# Create queue on 'not found' error
|
|
35
|
+
client.create_queue(
|
|
36
|
+
parent: client.location_path(project: config.gcp_project_id, location: config.gcp_location_id),
|
|
37
|
+
queue: {
|
|
38
|
+
name: full_queue_name,
|
|
39
|
+
retry_config: { max_attempts: queue_retries },
|
|
40
|
+
rate_limits: { max_concurrent_dispatches: queue_concurrency }
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Return the Google Cloud Task client.
|
|
47
|
+
#
|
|
48
|
+
# @return [Google::Cloud::Tasks::V2::CloudTasks::Client] The Google Cloud Task client.
|
|
49
|
+
#
|
|
50
|
+
def self.client
|
|
51
|
+
@client ||= ::Google::Cloud::Tasks.cloud_tasks
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# Return the cloudtasker configuration. See Cloudtasker#configure.
|
|
56
|
+
#
|
|
57
|
+
# @return [Cloudtasker::Config] The library configuration.
|
|
58
|
+
#
|
|
59
|
+
def self.config
|
|
60
|
+
Cloudtasker.config
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Return the fully qualified path for the Cloud Task queue.
|
|
65
|
+
#
|
|
66
|
+
# @param [String] queue_name The relative name of the queue.
|
|
67
|
+
#
|
|
68
|
+
# @return [String] The queue path.
|
|
69
|
+
#
|
|
70
|
+
def self.queue_path(queue_name)
|
|
71
|
+
client.queue_path(
|
|
72
|
+
project: config.gcp_project_id,
|
|
73
|
+
location: config.gcp_location_id,
|
|
74
|
+
queue: [config.gcp_queue_prefix, queue_name].join('-')
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Return a protobuf timestamp specifying how to wait
|
|
80
|
+
# before running a task.
|
|
81
|
+
#
|
|
82
|
+
# @param [Integer, nil] schedule_time A unix timestamp.
|
|
83
|
+
#
|
|
84
|
+
# @return [Google::Protobuf::Timestamp, nil] The protobuff timestamp
|
|
85
|
+
#
|
|
86
|
+
def self.format_schedule_time(schedule_time)
|
|
87
|
+
return nil unless schedule_time
|
|
88
|
+
|
|
89
|
+
# Generate protobuf timestamp
|
|
90
|
+
Google::Protobuf::Timestamp.new.tap { |e| e.seconds = schedule_time.to_i }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# Format the job payload sent to Cloud Tasks.
|
|
95
|
+
#
|
|
96
|
+
# @param [Hash] hash The worker payload.
|
|
97
|
+
#
|
|
98
|
+
# @return [Hash] The Cloud Task payloadd.
|
|
99
|
+
#
|
|
100
|
+
def self.format_task_payload(payload)
|
|
101
|
+
payload = JSON.parse(payload.to_json, symbolize_names: true) # deep dup
|
|
102
|
+
|
|
103
|
+
# Format schedule time to Google Protobuf timestamp
|
|
104
|
+
payload[:schedule_time] = format_schedule_time(payload[:schedule_time])
|
|
105
|
+
|
|
106
|
+
# Encode job content to support UTF-8.
|
|
107
|
+
# Google Cloud Task expect content to be ASCII-8BIT compatible (binary)
|
|
108
|
+
payload[:http_request][:headers] ||= {}
|
|
109
|
+
payload[:http_request][:headers][Cloudtasker::Config::CONTENT_TYPE_HEADER] = 'text/json'
|
|
110
|
+
payload[:http_request][:headers][Cloudtasker::Config::ENCODING_HEADER] = 'Base64'
|
|
111
|
+
payload[:http_request][:body] = Base64.encode64(payload[:http_request][:body])
|
|
112
|
+
|
|
113
|
+
payload
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# Find a task by id.
|
|
118
|
+
#
|
|
119
|
+
# @param [String] id The task id.
|
|
120
|
+
#
|
|
121
|
+
# @return [Cloudtasker::Backend::GoogleCloudTaskV2, nil] The retrieved task.
|
|
122
|
+
#
|
|
123
|
+
def self.find(id)
|
|
124
|
+
resp = with_gapi_retries { client.get_task(name: id) }
|
|
125
|
+
resp ? new(resp) : nil
|
|
126
|
+
rescue Google::Cloud::NotFoundError
|
|
127
|
+
# The ID does not exist
|
|
128
|
+
nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
#
|
|
132
|
+
# Create a new task.
|
|
133
|
+
#
|
|
134
|
+
# @param [Hash] payload The task payload.
|
|
135
|
+
#
|
|
136
|
+
# @return [Cloudtasker::Backend::GoogleCloudTaskV2, nil] The created task.
|
|
137
|
+
#
|
|
138
|
+
def self.create(payload)
|
|
139
|
+
payload = format_task_payload(payload)
|
|
140
|
+
|
|
141
|
+
# Infer full queue name
|
|
142
|
+
relative_queue = payload.delete(:queue)
|
|
143
|
+
full_queue = queue_path(relative_queue)
|
|
144
|
+
|
|
145
|
+
# Create task
|
|
146
|
+
resp = with_gapi_retries { client.create_task(parent: full_queue, task: payload) }
|
|
147
|
+
resp ? new(resp) : nil
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
#
|
|
151
|
+
# Delete a task by id.
|
|
152
|
+
#
|
|
153
|
+
# @param [String] id The id of the task.
|
|
154
|
+
#
|
|
155
|
+
def self.delete(id)
|
|
156
|
+
with_gapi_retries { client.delete_task(name: id) }
|
|
157
|
+
rescue Google::Cloud::NotFoundError, Google::Cloud::PermissionDeniedError
|
|
158
|
+
# The ID does not exist
|
|
159
|
+
nil
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
#
|
|
163
|
+
# Helper method encapsulating the retry strategy for Google API calls
|
|
164
|
+
#
|
|
165
|
+
def self.with_gapi_retries
|
|
166
|
+
Retriable.retriable(on: [Google::Cloud::UnavailableError], tries: 3) do
|
|
167
|
+
yield
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
#
|
|
172
|
+
# Build a new instance of the class.
|
|
173
|
+
#
|
|
174
|
+
# @param [Google::Cloud::Tasks::V2::Task] resp The GCP Cloud Task response
|
|
175
|
+
#
|
|
176
|
+
def initialize(gcp_task)
|
|
177
|
+
@gcp_task = gcp_task
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
#
|
|
181
|
+
# Return the relative queue (queue name minus prefix) the task is in.
|
|
182
|
+
#
|
|
183
|
+
# @return [String] The relative queue name
|
|
184
|
+
#
|
|
185
|
+
def relative_queue
|
|
186
|
+
gcp_task
|
|
187
|
+
.name
|
|
188
|
+
.match(%r{/queues/([^/]+)})
|
|
189
|
+
&.captures
|
|
190
|
+
&.first
|
|
191
|
+
&.sub("#{self.class.config.gcp_queue_prefix}-", '')
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
#
|
|
195
|
+
# Return a hash description of the task.
|
|
196
|
+
#
|
|
197
|
+
# @return [Hash] A hash description of the task.
|
|
198
|
+
#
|
|
199
|
+
def to_h
|
|
200
|
+
{
|
|
201
|
+
id: gcp_task.name,
|
|
202
|
+
http_request: gcp_task.to_h[:http_request],
|
|
203
|
+
schedule_time: gcp_task.to_h.dig(:schedule_time, :seconds).to_i,
|
|
204
|
+
retries: gcp_task.to_h[:response_count],
|
|
205
|
+
queue: relative_queue
|
|
206
|
+
}
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -62,7 +62,7 @@ module Cloudtasker
|
|
|
62
62
|
payload = payload.merge(schedule_time: payload[:schedule_time].to_i)
|
|
63
63
|
|
|
64
64
|
# Save task
|
|
65
|
-
task = new(payload.merge(id: id))
|
|
65
|
+
task = new(**payload.merge(id: id))
|
|
66
66
|
queue << task
|
|
67
67
|
|
|
68
68
|
# Execute task immediately if in testing and inline mode enabled
|
|
@@ -89,7 +89,7 @@ module Cloudtasker
|
|
|
89
89
|
# Save job
|
|
90
90
|
redis.write(key(id), payload)
|
|
91
91
|
redis.sadd(key, id)
|
|
92
|
-
new(payload.merge(id: id))
|
|
92
|
+
new(**payload.merge(id: id))
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
#
|
|
@@ -103,7 +103,7 @@ module Cloudtasker
|
|
|
103
103
|
gid = key(id)
|
|
104
104
|
return nil unless (payload = redis.fetch(gid))
|
|
105
105
|
|
|
106
|
-
new(payload.merge(id: id))
|
|
106
|
+
new(**payload.merge(id: id))
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
#
|
|
@@ -172,8 +172,12 @@ module Cloudtasker
|
|
|
172
172
|
# Retry the task later.
|
|
173
173
|
#
|
|
174
174
|
# @param [Integer] interval The delay in seconds before retrying the task
|
|
175
|
+
# @param [Hash] opts Additional options
|
|
176
|
+
# @option opts [Boolean] :is_error Increase number of retries. Default to true.
|
|
175
177
|
#
|
|
176
|
-
def retry_later(interval,
|
|
178
|
+
def retry_later(interval, opts = {})
|
|
179
|
+
is_error = opts.to_h.fetch(:is_error, true)
|
|
180
|
+
|
|
177
181
|
redis.write(
|
|
178
182
|
gid,
|
|
179
183
|
retries: is_error ? retries + 1 : retries,
|
|
@@ -8,7 +8,12 @@ module Cloudtasker
|
|
|
8
8
|
#
|
|
9
9
|
# The backend to use for cloud tasks.
|
|
10
10
|
#
|
|
11
|
-
# @return [
|
|
11
|
+
# @return [
|
|
12
|
+
# Backend::MemoryTask,
|
|
13
|
+
# Cloudtasker::Backend::GoogleCloudTaskV1,
|
|
14
|
+
# Cloudtasker::Backend::GoogleCloudTaskV2,
|
|
15
|
+
# Cloudtasker::Backend::RedisTask
|
|
16
|
+
# ] The cloud task backend.
|
|
12
17
|
#
|
|
13
18
|
def self.backend
|
|
14
19
|
# Re-evaluate backend every time if testing mode enabled
|
|
@@ -22,12 +27,45 @@ module Cloudtasker
|
|
|
22
27
|
require 'cloudtasker/backend/redis_task'
|
|
23
28
|
Backend::RedisTask
|
|
24
29
|
else
|
|
25
|
-
|
|
26
|
-
Backend::GoogleCloudTask
|
|
30
|
+
gct_backend
|
|
27
31
|
end
|
|
28
32
|
end
|
|
29
33
|
end
|
|
30
34
|
|
|
35
|
+
#
|
|
36
|
+
# Return the GoogleCloudTaskV* backend to use based on the version
|
|
37
|
+
# of the currently installed google-cloud-tasks gem
|
|
38
|
+
#
|
|
39
|
+
# @return [
|
|
40
|
+
# Cloudtasker::Backend::GoogleCloudTaskV1,
|
|
41
|
+
# Cloudtasker::Backend::GoogleCloudTaskV2
|
|
42
|
+
# ] The google cloud task backend.
|
|
43
|
+
#
|
|
44
|
+
def self.gct_backend
|
|
45
|
+
@gct_backend ||= begin
|
|
46
|
+
if !defined?(Google::Cloud::Tasks::VERSION) || Google::Cloud::Tasks::VERSION < '2'
|
|
47
|
+
require 'cloudtasker/backend/google_cloud_task_v1'
|
|
48
|
+
Backend::GoogleCloudTaskV1
|
|
49
|
+
else
|
|
50
|
+
require 'cloudtasker/backend/google_cloud_task_v2'
|
|
51
|
+
Backend::GoogleCloudTaskV2
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Create the google cloud task queue based on provided parameters if it does not exist already.
|
|
58
|
+
#
|
|
59
|
+
# @param [String] :name The queue name
|
|
60
|
+
# @param [Integer] :concurrency The queue concurrency
|
|
61
|
+
# @param [Integer] :retries The number of retries for the queue
|
|
62
|
+
#
|
|
63
|
+
# @return [Google::Cloud::Tasks::V2::Queue, Google::Cloud::Tasks::V2beta3::Queue] The queue
|
|
64
|
+
#
|
|
65
|
+
def self.setup_production_queue(**kwargs)
|
|
66
|
+
gct_backend.setup_queue(**kwargs)
|
|
67
|
+
end
|
|
68
|
+
|
|
31
69
|
#
|
|
32
70
|
# Find a cloud task by id.
|
|
33
71
|
#
|
|
@@ -37,7 +75,7 @@ module Cloudtasker
|
|
|
37
75
|
#
|
|
38
76
|
def self.find(id)
|
|
39
77
|
payload = backend.find(id)&.to_h
|
|
40
|
-
payload ? new(payload) : nil
|
|
78
|
+
payload ? new(**payload) : nil
|
|
41
79
|
end
|
|
42
80
|
|
|
43
81
|
#
|
|
@@ -51,7 +89,7 @@ module Cloudtasker
|
|
|
51
89
|
raise MaxTaskSizeExceededError if payload.to_json.bytesize > Config::MAX_TASK_SIZE
|
|
52
90
|
|
|
53
91
|
resp = backend.create(payload)&.to_h
|
|
54
|
-
resp ? new(resp) : nil
|
|
92
|
+
resp ? new(**resp) : nil
|
|
55
93
|
end
|
|
56
94
|
|
|
57
95
|
#
|
|
@@ -62,7 +62,7 @@ module Cloudtasker
|
|
|
62
62
|
def self.load_from_hash!(hash)
|
|
63
63
|
schedules = hash.map do |id, config|
|
|
64
64
|
schedule_config = JSON.parse(config.to_json, symbolize_names: true).merge(id: id.to_s)
|
|
65
|
-
create(schedule_config)
|
|
65
|
+
create(**schedule_config)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# Remove existing schedules which are not part of the list
|
|
@@ -79,7 +79,7 @@ module Cloudtasker
|
|
|
79
79
|
def self.create(**opts)
|
|
80
80
|
redis.with_lock(key(opts[:id])) do
|
|
81
81
|
config = find(opts[:id]).to_h.merge(opts)
|
|
82
|
-
new(config).tap(&:save)
|
|
82
|
+
new(**config).tap(&:save)
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
@@ -93,7 +93,7 @@ module Cloudtasker
|
|
|
93
93
|
def self.find(id)
|
|
94
94
|
return nil unless (schedule_config = redis.fetch(key(id)))
|
|
95
95
|
|
|
96
|
-
new(schedule_config)
|
|
96
|
+
new(**schedule_config)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
#
|
|
@@ -251,9 +251,9 @@ module Cloudtasker
|
|
|
251
251
|
#
|
|
252
252
|
# Buld edit the object attributes.
|
|
253
253
|
#
|
|
254
|
-
# @param [Hash]
|
|
254
|
+
# @param [Hash] opts The attributes to edit.
|
|
255
255
|
#
|
|
256
|
-
def assign_attributes(
|
|
256
|
+
def assign_attributes(opts)
|
|
257
257
|
opts
|
|
258
258
|
.select { |k, _| instance_variables.include?("@#{k}".to_sym) }
|
|
259
259
|
.each { |k, v| instance_variable_set("@#{k}", v) }
|
|
@@ -262,9 +262,9 @@ module Cloudtasker
|
|
|
262
262
|
#
|
|
263
263
|
# Edit the object attributes and save the object in Redis.
|
|
264
264
|
#
|
|
265
|
-
# @param [Hash]
|
|
265
|
+
# @param [Hash] opts The attributes to edit.
|
|
266
266
|
#
|
|
267
|
-
def update(
|
|
267
|
+
def update(opts)
|
|
268
268
|
assign_attributes(opts)
|
|
269
269
|
save
|
|
270
270
|
end
|
|
@@ -132,22 +132,47 @@ module Cloudtasker
|
|
|
132
132
|
list
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
# rubocop:disable Style/MissingRespondToMissing
|
|
136
|
+
if RUBY_VERSION < '3'
|
|
137
|
+
#
|
|
138
|
+
# Delegate all methods to the redis client.
|
|
139
|
+
# Old delegation method.
|
|
140
|
+
#
|
|
141
|
+
# @param [String, Symbol] name The method to delegate.
|
|
142
|
+
# @param [Array<any>] *args The list of method positional arguments.
|
|
143
|
+
# @param [Hash<any>] *kwargs The list of method keyword arguments.
|
|
144
|
+
# @param [Proc] &block Block passed to the method.
|
|
145
|
+
#
|
|
146
|
+
# @return [Any] The method return value
|
|
147
|
+
#
|
|
148
|
+
def method_missing(name, *args, &block)
|
|
149
|
+
if Redis.method_defined?(name)
|
|
150
|
+
client.with { |c| c.send(name, *args, &block) }
|
|
151
|
+
else
|
|
152
|
+
super
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
#
|
|
157
|
+
# Delegate all methods to the redis client.
|
|
158
|
+
# Ruby 3 delegation method style.
|
|
159
|
+
#
|
|
160
|
+
# @param [String, Symbol] name The method to delegate.
|
|
161
|
+
# @param [Array<any>] *args The list of method positional arguments.
|
|
162
|
+
# @param [Hash<any>] *kwargs The list of method keyword arguments.
|
|
163
|
+
# @param [Proc] &block Block passed to the method.
|
|
164
|
+
#
|
|
165
|
+
# @return [Any] The method return value
|
|
166
|
+
#
|
|
167
|
+
def method_missing(name, *args, **kwargs, &block)
|
|
168
|
+
if Redis.method_defined?(name)
|
|
169
|
+
client.with { |c| c.send(name, *args, **kwargs, &block) }
|
|
170
|
+
else
|
|
171
|
+
super
|
|
172
|
+
end
|
|
149
173
|
end
|
|
150
174
|
end
|
|
175
|
+
# rubocop:enable Style/MissingRespondToMissing
|
|
151
176
|
|
|
152
177
|
#
|
|
153
178
|
# Check if the class respond to a certain method.
|
|
@@ -14,10 +14,11 @@ module Cloudtasker
|
|
|
14
14
|
# Build a new instance of the class.
|
|
15
15
|
#
|
|
16
16
|
# @param [Cloudtasker::Worker] worker The worker at hand
|
|
17
|
+
# @param [Hash] worker The worker options
|
|
17
18
|
#
|
|
18
|
-
def initialize(worker,
|
|
19
|
+
def initialize(worker, opts = {})
|
|
19
20
|
@worker = worker
|
|
20
|
-
@call_opts =
|
|
21
|
+
@call_opts = opts
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
#
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
module Cloudtasker
|
|
4
4
|
module UniqueJob
|
|
5
5
|
module Middleware
|
|
6
|
+
# TODO: kwargs to job otherwise it won't get the time_at
|
|
6
7
|
# Client middleware, invoked when jobs are scheduled
|
|
7
8
|
class Client
|
|
8
|
-
def call(worker,
|
|
9
|
+
def call(worker, _opts = {})
|
|
9
10
|
Job.new(worker).lock_instance.schedule { yield }
|
|
10
11
|
end
|
|
11
12
|
end
|
data/lib/cloudtasker/version.rb
CHANGED
data/lib/cloudtasker/worker.rb
CHANGED
|
@@ -47,7 +47,7 @@ module Cloudtasker
|
|
|
47
47
|
return nil unless worker_klass.include?(self)
|
|
48
48
|
|
|
49
49
|
# Return instantiated worker
|
|
50
|
-
worker_klass.new(payload.slice(:job_queue, :job_args, :job_id, :job_meta, :job_retries, :task_id))
|
|
50
|
+
worker_klass.new(**payload.slice(:job_queue, :job_args, :job_id, :job_meta, :job_retries, :task_id))
|
|
51
51
|
rescue NameError
|
|
52
52
|
nil
|
|
53
53
|
end
|
|
@@ -121,7 +121,7 @@ module Cloudtasker
|
|
|
121
121
|
# @return [Cloudtasker::CloudTask] The Google Task response
|
|
122
122
|
#
|
|
123
123
|
def schedule(args: nil, time_in: nil, time_at: nil, queue: nil)
|
|
124
|
-
new(job_args: args, job_queue: queue).schedule({ interval: time_in, time_at: time_at }.compact)
|
|
124
|
+
new(job_args: args, job_queue: queue).schedule(**{ interval: time_in, time_at: time_at }.compact)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
#
|
|
@@ -239,7 +239,7 @@ module Cloudtasker
|
|
|
239
239
|
#
|
|
240
240
|
def schedule(**args)
|
|
241
241
|
# Evaluate when to schedule the job
|
|
242
|
-
time_at = schedule_time(args)
|
|
242
|
+
time_at = schedule_time(**args)
|
|
243
243
|
|
|
244
244
|
# Schedule job through client middlewares
|
|
245
245
|
Cloudtasker.config.client_middleware.invoke(self, time_at: time_at) do
|
data/lib/tasks/setup_queue.rake
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'cloudtasker/backend/google_cloud_task'
|
|
4
3
|
require 'cloudtasker/config'
|
|
4
|
+
require 'cloudtasker/cloud_task'
|
|
5
5
|
|
|
6
6
|
ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] ||= 'true'
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ namespace :cloudtasker do
|
|
|
11
11
|
"concurrency=#{Cloudtasker::Config::DEFAULT_QUEUE_CONCURRENCY}, " \
|
|
12
12
|
"retries=#{Cloudtasker::Config::DEFAULT_QUEUE_RETRIES})"
|
|
13
13
|
task setup_queue: :environment do
|
|
14
|
-
puts Cloudtasker::
|
|
14
|
+
puts Cloudtasker::CloudTask.setup_production_queue(
|
|
15
15
|
name: ENV['name'],
|
|
16
16
|
concurrency: ENV['concurrency'],
|
|
17
17
|
retries: ENV['retries']
|