cloudtasker 0.9.5 → 0.10.rc1
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/.rubocop.yml +1 -1
- data/.travis.yml +16 -0
- data/Appraisals +0 -16
- data/CHANGELOG.md +0 -22
- data/README.md +40 -1
- data/app/controllers/cloudtasker/application_controller.rb +8 -0
- data/app/controllers/cloudtasker/worker_controller.rb +1 -4
- data/cloudtasker.gemspec +1 -2
- data/gemfiles/google_cloud_tasks_1.0.gemfile +5 -3
- data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +154 -208
- data/gemfiles/google_cloud_tasks_1.1.gemfile +5 -3
- data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +154 -208
- data/gemfiles/google_cloud_tasks_1.2.gemfile +5 -3
- data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +154 -208
- data/gemfiles/google_cloud_tasks_1.3.gemfile +5 -3
- data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +154 -208
- data/gemfiles/rails_5.2.gemfile +5 -3
- data/gemfiles/rails_5.2.gemfile.lock +91 -146
- data/gemfiles/rails_6.0.gemfile +5 -3
- data/gemfiles/rails_6.0.gemfile.lock +92 -147
- data/lib/cloudtasker/backend/google_cloud_task.rb +1 -1
- data/lib/cloudtasker/backend/memory_task.rb +8 -23
- data/lib/cloudtasker/config.rb +16 -1
- data/lib/cloudtasker/testing.rb +2 -2
- data/lib/cloudtasker/version.rb +1 -1
- data/lib/cloudtasker/worker_handler.rb +142 -5
- data/lib/cloudtasker/worker_logger.rb +1 -2
- data/lib/cloudtasker.rb +0 -1
- metadata +15 -32
- data/.github/workflows/test.yml +0 -45
- data/gemfiles/semantic_logger_3.4.gemfile +0 -7
- data/gemfiles/semantic_logger_4.6.gemfile +0 -7
- data/gemfiles/semantic_logger_4.7.0.gemfile +0 -7
- data/gemfiles/semantic_logger_4.7.2.gemfile +0 -7
- data/gemfiles/semantic_logger_4.7.gemfile +0 -9
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
cloudtasker (0.
|
4
|
+
cloudtasker (0.10.rc1)
|
5
5
|
activesupport
|
6
6
|
fugit
|
7
|
-
google-cloud-tasks
|
7
|
+
google-cloud-tasks
|
8
8
|
jwt
|
9
9
|
redis
|
10
10
|
|
@@ -66,79 +66,40 @@ GEM
|
|
66
66
|
minitest (~> 5.1)
|
67
67
|
tzinfo (~> 1.1)
|
68
68
|
zeitwerk (~> 2.1, >= 2.1.8)
|
69
|
-
addressable (2.
|
69
|
+
addressable (2.7.0)
|
70
70
|
public_suffix (>= 2.0.2, < 5.0)
|
71
|
-
appraisal (2.
|
71
|
+
appraisal (2.2.0)
|
72
72
|
bundler
|
73
73
|
rake
|
74
74
|
thor (>= 0.14.0)
|
75
|
-
ast (2.4.
|
76
|
-
async (1.30.1)
|
77
|
-
console (~> 1.10)
|
78
|
-
nio4r (~> 2.3)
|
79
|
-
timers (~> 4.1)
|
80
|
-
async-http (0.56.5)
|
81
|
-
async (>= 1.25)
|
82
|
-
async-io (>= 1.28)
|
83
|
-
async-pool (>= 0.2)
|
84
|
-
protocol-http (~> 0.22.0)
|
85
|
-
protocol-http1 (~> 0.14.0)
|
86
|
-
protocol-http2 (~> 0.14.0)
|
87
|
-
async-http-faraday (0.11.0)
|
88
|
-
async-http (~> 0.42)
|
89
|
-
faraday
|
90
|
-
async-io (1.32.2)
|
91
|
-
async
|
92
|
-
async-pool (0.3.8)
|
93
|
-
async (>= 1.25)
|
75
|
+
ast (2.4.0)
|
94
76
|
builder (3.2.4)
|
95
|
-
concurrent-ruby (1.1.
|
96
|
-
|
97
|
-
|
98
|
-
crack (0.4.5)
|
99
|
-
rexml
|
77
|
+
concurrent-ruby (1.1.6)
|
78
|
+
crack (0.4.3)
|
79
|
+
safe_yaml (~> 1.0.0)
|
100
80
|
crass (1.0.6)
|
101
|
-
diff-lcs (1.
|
102
|
-
erubi (1.
|
103
|
-
et-orbi (1.2.
|
81
|
+
diff-lcs (1.3)
|
82
|
+
erubi (1.9.0)
|
83
|
+
et-orbi (1.2.3)
|
104
84
|
tzinfo
|
105
|
-
faraday (
|
106
|
-
faraday-em_http (~> 1.0)
|
107
|
-
faraday-em_synchrony (~> 1.0)
|
108
|
-
faraday-excon (~> 1.1)
|
109
|
-
faraday-httpclient (~> 1.0.1)
|
110
|
-
faraday-net_http (~> 1.0)
|
111
|
-
faraday-net_http_persistent (~> 1.1)
|
112
|
-
faraday-patron (~> 1.0)
|
113
|
-
faraday-rack (~> 1.0)
|
85
|
+
faraday (0.17.3)
|
114
86
|
multipart-post (>= 1.2, < 3)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
faraday-excon (1.1.0)
|
119
|
-
faraday-http-cache (2.2.0)
|
120
|
-
faraday (>= 0.8)
|
121
|
-
faraday-httpclient (1.0.1)
|
122
|
-
faraday-net_http (1.0.1)
|
123
|
-
faraday-net_http_persistent (1.2.0)
|
124
|
-
faraday-patron (1.0.0)
|
125
|
-
faraday-rack (1.0.0)
|
126
|
-
fiber-local (1.0.0)
|
127
|
-
fugit (1.5.1)
|
87
|
+
faraday-http-cache (2.0.0)
|
88
|
+
faraday (~> 0.8)
|
89
|
+
fugit (1.3.3)
|
128
90
|
et-orbi (~> 1.1, >= 1.1.8)
|
129
|
-
raabro (~> 1.
|
130
|
-
github_changelog_generator (1.
|
91
|
+
raabro (~> 1.1)
|
92
|
+
github_changelog_generator (1.15.0)
|
131
93
|
activesupport
|
132
|
-
async (>= 1.25.0)
|
133
|
-
async-http-faraday
|
134
94
|
faraday-http-cache
|
135
95
|
multi_json
|
136
96
|
octokit (~> 4.6)
|
137
97
|
rainbow (>= 2.2.1)
|
138
98
|
rake (>= 10.0)
|
139
|
-
|
140
|
-
|
141
|
-
|
99
|
+
retriable (~> 3.0)
|
100
|
+
globalid (0.4.2)
|
101
|
+
activesupport (>= 4.2.0)
|
102
|
+
google-cloud-tasks (1.4.0)
|
142
103
|
google-gax (~> 1.8)
|
143
104
|
googleapis-common-protos (>= 1.3.9, < 2.0)
|
144
105
|
googleapis-common-protos-types (>= 1.0.4, < 2.0)
|
@@ -149,33 +110,32 @@ GEM
|
|
149
110
|
googleauth (~> 0.9)
|
150
111
|
grpc (~> 1.24)
|
151
112
|
rly (~> 0.2.3)
|
152
|
-
google-protobuf (3.
|
153
|
-
googleapis-common-protos (1.3.
|
154
|
-
google-protobuf (~> 3.
|
155
|
-
googleapis-common-protos-types (
|
156
|
-
grpc (~> 1.
|
157
|
-
googleapis-common-protos-types (1.
|
158
|
-
google-protobuf (~> 3.
|
159
|
-
googleauth (0.
|
113
|
+
google-protobuf (3.11.4)
|
114
|
+
googleapis-common-protos (1.3.9)
|
115
|
+
google-protobuf (~> 3.0)
|
116
|
+
googleapis-common-protos-types (~> 1.0)
|
117
|
+
grpc (~> 1.0)
|
118
|
+
googleapis-common-protos-types (1.0.4)
|
119
|
+
google-protobuf (~> 3.0)
|
120
|
+
googleauth (0.11.0)
|
160
121
|
faraday (>= 0.17.3, < 2.0)
|
161
122
|
jwt (>= 1.4, < 3.0)
|
162
123
|
memoist (~> 0.16)
|
163
124
|
multi_json (~> 1.11)
|
164
125
|
os (>= 0.9, < 2.0)
|
165
|
-
signet (~> 0.
|
166
|
-
grpc (1.
|
167
|
-
google-protobuf (~> 3.
|
126
|
+
signet (~> 0.12)
|
127
|
+
grpc (1.27.0)
|
128
|
+
google-protobuf (~> 3.11)
|
168
129
|
googleapis-common-protos-types (~> 1.0)
|
169
|
-
grpc-google-iam-v1 (0.6.
|
170
|
-
|
171
|
-
|
172
|
-
grpc (~> 1.27)
|
130
|
+
grpc-google-iam-v1 (0.6.9)
|
131
|
+
googleapis-common-protos (>= 1.3.1, < 2.0)
|
132
|
+
grpc (~> 1.0)
|
173
133
|
hashdiff (1.0.1)
|
174
|
-
i18n (1.8.
|
134
|
+
i18n (1.8.2)
|
175
135
|
concurrent-ruby (~> 1.0)
|
176
136
|
jaro_winkler (1.5.4)
|
177
|
-
jwt (2.2.
|
178
|
-
loofah (2.
|
137
|
+
jwt (2.2.1)
|
138
|
+
loofah (2.4.0)
|
179
139
|
crass (~> 1.0.2)
|
180
140
|
nokogiri (>= 1.5.9)
|
181
141
|
mail (2.7.1)
|
@@ -183,37 +143,26 @@ GEM
|
|
183
143
|
marcel (0.3.3)
|
184
144
|
mimemagic (~> 0.3.2)
|
185
145
|
memoist (0.16.2)
|
186
|
-
method_source (
|
187
|
-
mimemagic (0.3.
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
minitest (5.14.4)
|
193
|
-
multi_json (1.15.0)
|
146
|
+
method_source (0.9.2)
|
147
|
+
mimemagic (0.3.4)
|
148
|
+
mini_mime (1.0.2)
|
149
|
+
mini_portile2 (2.4.0)
|
150
|
+
minitest (5.14.0)
|
151
|
+
multi_json (1.14.1)
|
194
152
|
multipart-post (2.1.1)
|
195
|
-
nio4r (2.5.
|
196
|
-
nokogiri (1.
|
197
|
-
mini_portile2 (~> 2.
|
198
|
-
|
199
|
-
octokit (4.21.0)
|
153
|
+
nio4r (2.5.2)
|
154
|
+
nokogiri (1.10.9)
|
155
|
+
mini_portile2 (~> 2.4.0)
|
156
|
+
octokit (4.16.0)
|
200
157
|
faraday (>= 0.9)
|
201
158
|
sawyer (~> 0.8.0, >= 0.5.3)
|
202
|
-
os (1.
|
203
|
-
parallel (1.
|
204
|
-
parser (
|
205
|
-
ast (~> 2.4.
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
protocol-http (~> 0.22)
|
210
|
-
protocol-http2 (0.14.2)
|
211
|
-
protocol-hpack (~> 1.4)
|
212
|
-
protocol-http (~> 0.18)
|
213
|
-
public_suffix (4.0.6)
|
214
|
-
raabro (1.4.0)
|
215
|
-
racc (1.5.2)
|
216
|
-
rack (2.2.3)
|
159
|
+
os (1.0.1)
|
160
|
+
parallel (1.19.1)
|
161
|
+
parser (2.7.0.4)
|
162
|
+
ast (~> 2.4.0)
|
163
|
+
public_suffix (4.0.3)
|
164
|
+
raabro (1.1.6)
|
165
|
+
rack (2.2.2)
|
217
166
|
rack-test (1.1.0)
|
218
167
|
rack (>= 1.0, < 3)
|
219
168
|
rails (6.0.0)
|
@@ -234,7 +183,7 @@ GEM
|
|
234
183
|
rails-dom-testing (2.0.3)
|
235
184
|
activesupport (>= 4.2.0)
|
236
185
|
nokogiri (>= 1.6)
|
237
|
-
rails-html-sanitizer (1.
|
186
|
+
rails-html-sanitizer (1.3.0)
|
238
187
|
loofah (~> 2.3)
|
239
188
|
railties (6.0.0)
|
240
189
|
actionpack (= 6.0.0)
|
@@ -243,31 +192,31 @@ GEM
|
|
243
192
|
rake (>= 0.8.7)
|
244
193
|
thor (>= 0.20.3, < 2.0)
|
245
194
|
rainbow (3.0.0)
|
246
|
-
rake (13.0.
|
247
|
-
redis (4.
|
248
|
-
|
195
|
+
rake (13.0.1)
|
196
|
+
redis (4.1.3)
|
197
|
+
retriable (3.1.2)
|
249
198
|
rly (0.2.3)
|
250
|
-
rspec (3.
|
251
|
-
rspec-core (~> 3.
|
252
|
-
rspec-expectations (~> 3.
|
253
|
-
rspec-mocks (~> 3.
|
254
|
-
rspec-core (3.
|
255
|
-
rspec-support (~> 3.
|
256
|
-
rspec-expectations (3.
|
199
|
+
rspec (3.9.0)
|
200
|
+
rspec-core (~> 3.9.0)
|
201
|
+
rspec-expectations (~> 3.9.0)
|
202
|
+
rspec-mocks (~> 3.9.0)
|
203
|
+
rspec-core (3.9.1)
|
204
|
+
rspec-support (~> 3.9.1)
|
205
|
+
rspec-expectations (3.9.0)
|
257
206
|
diff-lcs (>= 1.2.0, < 2.0)
|
258
|
-
rspec-support (~> 3.
|
259
|
-
rspec-mocks (3.
|
207
|
+
rspec-support (~> 3.9.0)
|
208
|
+
rspec-mocks (3.9.1)
|
260
209
|
diff-lcs (>= 1.2.0, < 2.0)
|
261
|
-
rspec-support (~> 3.
|
262
|
-
rspec-rails (
|
263
|
-
actionpack (>=
|
264
|
-
activesupport (>=
|
265
|
-
railties (>=
|
266
|
-
rspec-core (~> 3.
|
267
|
-
rspec-expectations (~> 3.
|
268
|
-
rspec-mocks (~> 3.
|
269
|
-
rspec-support (~> 3.
|
270
|
-
rspec-support (3.
|
210
|
+
rspec-support (~> 3.9.0)
|
211
|
+
rspec-rails (3.9.0)
|
212
|
+
actionpack (>= 3.0)
|
213
|
+
activesupport (>= 3.0)
|
214
|
+
railties (>= 3.0)
|
215
|
+
rspec-core (~> 3.9.0)
|
216
|
+
rspec-expectations (~> 3.9.0)
|
217
|
+
rspec-mocks (~> 3.9.0)
|
218
|
+
rspec-support (~> 3.9.0)
|
219
|
+
rspec-support (3.9.2)
|
271
220
|
rubocop (0.76.0)
|
272
221
|
jaro_winkler (~> 1.5.1)
|
273
222
|
parallel (~> 1.10)
|
@@ -277,41 +226,38 @@ GEM
|
|
277
226
|
unicode-display_width (>= 1.4.0, < 1.7)
|
278
227
|
rubocop-rspec (1.37.0)
|
279
228
|
rubocop (>= 0.68.1)
|
280
|
-
ruby-progressbar (1.
|
281
|
-
|
229
|
+
ruby-progressbar (1.10.1)
|
230
|
+
safe_yaml (1.0.5)
|
282
231
|
sawyer (0.8.2)
|
283
232
|
addressable (>= 2.3.5)
|
284
233
|
faraday (> 0.8, < 2.0)
|
285
|
-
|
286
|
-
concurrent-ruby (~> 1.0)
|
287
|
-
signet (0.15.0)
|
234
|
+
signet (0.13.0)
|
288
235
|
addressable (~> 2.3)
|
289
236
|
faraday (>= 0.17.3, < 2.0)
|
290
237
|
jwt (>= 1.5, < 3.0)
|
291
238
|
multi_json (~> 1.10)
|
292
|
-
sprockets (4.0.
|
239
|
+
sprockets (4.0.0)
|
293
240
|
concurrent-ruby (~> 1.0)
|
294
241
|
rack (> 1, < 3)
|
295
|
-
sprockets-rails (3.2.
|
242
|
+
sprockets-rails (3.2.1)
|
296
243
|
actionpack (>= 4.0)
|
297
244
|
activesupport (>= 4.0)
|
298
245
|
sprockets (>= 3.0.0)
|
299
246
|
sqlite3 (1.4.2)
|
300
|
-
thor (1.1
|
247
|
+
thor (1.0.1)
|
301
248
|
thread_safe (0.3.6)
|
302
|
-
timecop (0.9.
|
303
|
-
|
304
|
-
tzinfo (1.2.9)
|
249
|
+
timecop (0.9.1)
|
250
|
+
tzinfo (1.2.6)
|
305
251
|
thread_safe (~> 0.1)
|
306
252
|
unicode-display_width (1.6.1)
|
307
|
-
webmock (3.
|
308
|
-
addressable (>= 2.
|
253
|
+
webmock (3.8.2)
|
254
|
+
addressable (>= 2.3.6)
|
309
255
|
crack (>= 0.3.2)
|
310
256
|
hashdiff (>= 0.4.0, < 2.0.0)
|
311
|
-
websocket-driver (0.7.
|
257
|
+
websocket-driver (0.7.1)
|
312
258
|
websocket-extensions (>= 0.1.0)
|
313
|
-
websocket-extensions (0.1.
|
314
|
-
zeitwerk (2.
|
259
|
+
websocket-extensions (0.1.4)
|
260
|
+
zeitwerk (2.3.0)
|
315
261
|
|
316
262
|
PLATFORMS
|
317
263
|
ruby
|
@@ -327,10 +273,9 @@ DEPENDENCIES
|
|
327
273
|
rspec-rails
|
328
274
|
rubocop (= 0.76.0)
|
329
275
|
rubocop-rspec (= 1.37.0)
|
330
|
-
semantic_logger
|
331
276
|
sqlite3
|
332
277
|
timecop
|
333
278
|
webmock
|
334
279
|
|
335
280
|
BUNDLED WITH
|
336
|
-
2.
|
281
|
+
2.1.4
|
@@ -7,6 +7,7 @@ module Cloudtasker
|
|
7
7
|
# Manage local tasks pushed to memory.
|
8
8
|
# Used for testing.
|
9
9
|
class MemoryTask
|
10
|
+
attr_accessor :job_retries
|
10
11
|
attr_reader :id, :http_request, :schedule_time, :queue
|
11
12
|
|
12
13
|
#
|
@@ -18,17 +19,6 @@ module Cloudtasker
|
|
18
19
|
@queue ||= []
|
19
20
|
end
|
20
21
|
|
21
|
-
#
|
22
|
-
# Return the workers currently in the queue.
|
23
|
-
#
|
24
|
-
# @param [String] worker_class_name Filter jobs on worker class name.
|
25
|
-
#
|
26
|
-
# @return [Array<Cloudtasker::Worker] The list of workers
|
27
|
-
#
|
28
|
-
def self.jobs(worker_class_name = nil)
|
29
|
-
all(worker_class_name).map(&:worker)
|
30
|
-
end
|
31
|
-
|
32
22
|
#
|
33
23
|
# Run all Tasks in the queue. Optionally filter which tasks to run based
|
34
24
|
# on the worker class name.
|
@@ -116,11 +106,12 @@ module Cloudtasker
|
|
116
106
|
# @param [Hash] http_request The HTTP request content.
|
117
107
|
# @param [Integer] schedule_time When to run the task (Unix timestamp)
|
118
108
|
#
|
119
|
-
def initialize(id:, http_request:, schedule_time: nil, queue: nil)
|
109
|
+
def initialize(id:, http_request:, schedule_time: nil, queue: nil, job_retries: 0)
|
120
110
|
@id = id
|
121
111
|
@http_request = http_request
|
122
112
|
@schedule_time = Time.at(schedule_time || 0)
|
123
113
|
@queue = queue
|
114
|
+
@job_retries = job_retries || 0
|
124
115
|
end
|
125
116
|
|
126
117
|
#
|
@@ -155,26 +146,20 @@ module Cloudtasker
|
|
155
146
|
}
|
156
147
|
end
|
157
148
|
|
158
|
-
#
|
159
|
-
# Return the worker attached to this task.
|
160
|
-
#
|
161
|
-
# @return [Cloudtasker::Worker] The task worker.
|
162
|
-
#
|
163
|
-
def worker
|
164
|
-
@worker ||= Worker.from_hash(payload)
|
165
|
-
end
|
166
|
-
|
167
149
|
#
|
168
150
|
# Execute the task.
|
169
151
|
#
|
170
152
|
# @return [Any] The return value of the worker perform method.
|
171
153
|
#
|
172
154
|
def execute
|
173
|
-
|
155
|
+
# Execute worker
|
156
|
+
resp = WorkerHandler.with_worker_handling(payload, &:execute)
|
157
|
+
|
158
|
+
# Delete task
|
174
159
|
self.class.delete(id)
|
175
160
|
resp
|
176
161
|
rescue StandardError
|
177
|
-
|
162
|
+
self.job_retries += 1
|
178
163
|
end
|
179
164
|
|
180
165
|
#
|
data/lib/cloudtasker/config.rb
CHANGED
@@ -5,7 +5,7 @@ require 'logger'
|
|
5
5
|
module Cloudtasker
|
6
6
|
# Holds cloudtasker configuration. See Cloudtasker#configure
|
7
7
|
class Config
|
8
|
-
attr_accessor :redis
|
8
|
+
attr_accessor :redis, :store_payloads_in_redis
|
9
9
|
attr_writer :secret, :gcp_location_id, :gcp_project_id,
|
10
10
|
:gcp_queue_prefix, :processor_path, :logger, :mode, :max_retries
|
11
11
|
|
@@ -54,6 +54,21 @@ module Cloudtasker
|
|
54
54
|
Please specify a secret in the cloudtasker initializer or add Rails secret_key_base in your credentials
|
55
55
|
DOC
|
56
56
|
|
57
|
+
#
|
58
|
+
# Return the threshold above which job arguments must be stored
|
59
|
+
# in Redis instead of being sent to the backend as part of the job
|
60
|
+
# payload.
|
61
|
+
#
|
62
|
+
# Return nil if redis payload storage is disabled.
|
63
|
+
#
|
64
|
+
# @return [Integer, nil] The threshold above which payloads will be stored in Redis.
|
65
|
+
#
|
66
|
+
def redis_payload_storage_threshold
|
67
|
+
return nil unless store_payloads_in_redis
|
68
|
+
|
69
|
+
store_payloads_in_redis.respond_to?(:to_i) ? store_payloads_in_redis.to_i : 0
|
70
|
+
end
|
71
|
+
|
57
72
|
#
|
58
73
|
# The number of times jobs will be retried. This number of
|
59
74
|
# retries does not include failures due to the application being unreachable.
|
data/lib/cloudtasker/testing.rb
CHANGED
@@ -114,10 +114,10 @@ module Cloudtasker
|
|
114
114
|
#
|
115
115
|
# Return all jobs related to this worker class.
|
116
116
|
#
|
117
|
-
# @return [Array<Cloudtasker::
|
117
|
+
# @return [Array<Cloudtasker::Backend::MemoryTask>] The list of tasks
|
118
118
|
#
|
119
119
|
def jobs
|
120
|
-
Backend::MemoryTask.
|
120
|
+
Backend::MemoryTask.all(to_s)
|
121
121
|
end
|
122
122
|
|
123
123
|
#
|
data/lib/cloudtasker/version.rb
CHANGED
@@ -10,16 +10,113 @@ module Cloudtasker
|
|
10
10
|
# Alrogith used to sign the verification token
|
11
11
|
JWT_ALG = 'HS256'
|
12
12
|
|
13
|
+
# Sub-namespace to use for redis keys when storing
|
14
|
+
# payloads in Redis
|
15
|
+
REDIS_PAYLOAD_NAMESPACE = 'payload'
|
16
|
+
|
17
|
+
# Arg payload cache keys get expired instead of deleted
|
18
|
+
# in case jobs are re-processed due to connection interruption
|
19
|
+
# (job is successful but Cloud Task considers it as failed due
|
20
|
+
# to network interruption)
|
21
|
+
ARGS_PAYLOAD_CLEANUP_TTL = 3600 # 1 hour
|
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 the cloudtasker redis client
|
38
|
+
#
|
39
|
+
# @return [Cloudtasker::RedisClient] The cloudtasker redis client.
|
40
|
+
#
|
41
|
+
def self.redis
|
42
|
+
@redis ||= begin
|
43
|
+
require 'cloudtasker/redis_client'
|
44
|
+
RedisClient.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
13
48
|
#
|
14
49
|
# Execute a task worker from a task payload
|
15
50
|
#
|
16
|
-
# @param [Hash]
|
51
|
+
# @param [Hash] input_payload The Cloud Task payload.
|
17
52
|
#
|
18
53
|
# @return [Any] The return value of the worker perform method.
|
19
54
|
#
|
20
|
-
def self.execute_from_payload!(
|
55
|
+
def self.execute_from_payload!(input_payload)
|
56
|
+
with_worker_handling(input_payload, &:execute)
|
57
|
+
end
|
58
|
+
|
59
|
+
# TODO: do not delete redis payload if job has been re-enqueued
|
60
|
+
# worker.job_reenqueued
|
61
|
+
#
|
62
|
+
# Idea: change with_worker_handling to with_worker_handling and build the worker
|
63
|
+
# inside the with_worker_handling block.
|
64
|
+
#
|
65
|
+
# Local middleware used to retrieve the job arg payload from cache
|
66
|
+
# if a arg payload reference is present.
|
67
|
+
#
|
68
|
+
# @param [Hash] payload The full job payload
|
69
|
+
#
|
70
|
+
# @yield [Hash] The actual payload to use to process the job.
|
71
|
+
#
|
72
|
+
# @return [Any] The block result
|
73
|
+
#
|
74
|
+
def self.with_worker_handling(input_payload)
|
75
|
+
# Extract payload information
|
76
|
+
extracted_payload = extract_payload(input_payload)
|
77
|
+
payload = extracted_payload[:payload]
|
78
|
+
args_payload_key = extracted_payload[:args_payload_key]
|
79
|
+
|
80
|
+
# Build worker
|
21
81
|
worker = Cloudtasker::Worker.from_hash(payload) || raise(InvalidWorkerError)
|
22
|
-
|
82
|
+
|
83
|
+
# Yied worker
|
84
|
+
resp = yield(worker)
|
85
|
+
|
86
|
+
# Schedule args payload deletion after job has been successfully processed
|
87
|
+
# Note: we expire the key instead of deleting it immediately in case the job
|
88
|
+
# succeeds but is considered as failed by Cloud Task due to network interruption.
|
89
|
+
# In such case the job is likely to be re-processed soon after.
|
90
|
+
redis.expire(args_payload_key, ARGS_PAYLOAD_CLEANUP_TTL) if args_payload_key && !worker.job_reenqueued
|
91
|
+
|
92
|
+
resp
|
93
|
+
rescue DeadWorkerError => e
|
94
|
+
# Delete stored args payload if job is dead
|
95
|
+
redis.expire(args_payload_key, ARGS_PAYLOAD_CLEANUP_TTL) if args_payload_key
|
96
|
+
raise(e)
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Return the argument payload key (if present) along with the actual worker payload.
|
101
|
+
#
|
102
|
+
# If the payload was stored in Redis then retrieve it.
|
103
|
+
#
|
104
|
+
# @return [Hash] Hash
|
105
|
+
#
|
106
|
+
def self.extract_payload(input_payload)
|
107
|
+
# Get references
|
108
|
+
payload = JSON.parse(input_payload.to_json, symbolize_names: true)
|
109
|
+
args_payload_id = payload.delete(:job_args_payload_id)
|
110
|
+
args_payload_key = args_payload_id ? key([REDIS_PAYLOAD_NAMESPACE, args_payload_id].join('/')) : nil
|
111
|
+
|
112
|
+
# Retrieve the actual worker args payload
|
113
|
+
args_payload = args_payload_key ? redis.fetch(args_payload_key) : payload[:job_args]
|
114
|
+
|
115
|
+
# Return the payload
|
116
|
+
{
|
117
|
+
args_payload_key: args_payload_key,
|
118
|
+
payload: payload.merge(job_args: args_payload)
|
119
|
+
}
|
23
120
|
end
|
24
121
|
|
25
122
|
#
|
@@ -51,6 +148,47 @@ module Cloudtasker
|
|
51
148
|
}
|
52
149
|
end
|
53
150
|
|
151
|
+
#
|
152
|
+
# Return true if the worker args must be stored in Redis.
|
153
|
+
#
|
154
|
+
# @return [Boolean] True if the payload must be stored in redis.
|
155
|
+
#
|
156
|
+
def store_payload_in_redis?
|
157
|
+
Cloudtasker.config.redis_payload_storage_threshold &&
|
158
|
+
worker.job_args.to_json.bytesize > (Cloudtasker.config.redis_payload_storage_threshold * 1024)
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# Return the payload to use for job arguments. This payload
|
163
|
+
# is merged inside the #worker_payload.
|
164
|
+
#
|
165
|
+
# If the argument payload must be stored in Redis then returns:
|
166
|
+
# `{ job_args_payload_id: <worker_id> }`
|
167
|
+
#
|
168
|
+
# If the argument payload must be natively handled by the backend
|
169
|
+
# then returns:
|
170
|
+
# `{ job_args: [...] }`
|
171
|
+
#
|
172
|
+
# @return [Hash] The worker args payload.
|
173
|
+
#
|
174
|
+
def worker_args_payload
|
175
|
+
@worker_args_payload ||= begin
|
176
|
+
if store_payload_in_redis?
|
177
|
+
# Store payload in Redis
|
178
|
+
self.class.redis.write(
|
179
|
+
self.class.key([REDIS_PAYLOAD_NAMESPACE, worker.job_id].join('/')),
|
180
|
+
worker.job_args
|
181
|
+
)
|
182
|
+
|
183
|
+
# Return reference to args payload
|
184
|
+
{ job_args_payload_id: worker.job_id }
|
185
|
+
else
|
186
|
+
# Return regular job args payload
|
187
|
+
{ job_args: worker.job_args }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
54
192
|
#
|
55
193
|
# Return the task payload that Google Task will eventually
|
56
194
|
# send to the job processor.
|
@@ -68,9 +206,8 @@ module Cloudtasker
|
|
68
206
|
worker: worker.job_class_name,
|
69
207
|
job_queue: worker.job_queue,
|
70
208
|
job_id: worker.job_id,
|
71
|
-
job_args: worker.job_args,
|
72
209
|
job_meta: worker.job_meta.to_h
|
73
|
-
}
|
210
|
+
}.merge(worker_args_payload)
|
74
211
|
end
|
75
212
|
|
76
213
|
#
|
@@ -141,8 +141,7 @@ module Cloudtasker
|
|
141
141
|
# @param [Proc] &block Optional context block.
|
142
142
|
#
|
143
143
|
def log_message(level, msg, &block)
|
144
|
-
|
145
|
-
payload_block = ->(*_args) { log_block.call.merge(block&.call || {}) }
|
144
|
+
payload_block = block || log_block
|
146
145
|
|
147
146
|
# ActiveSupport::Logger does not support passing a payload through a block on top
|
148
147
|
# of a message.
|