cloudtasker 0.11.1 → 0.12.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/.github/workflows/test.yml +5 -1
- data/.rubocop.yml +8 -1
- data/CHANGELOG.md +10 -20
- data/app/controllers/cloudtasker/application_controller.rb +8 -0
- data/app/controllers/cloudtasker/worker_controller.rb +5 -21
- data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +95 -137
- data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +95 -137
- data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +95 -137
- data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +95 -137
- data/gemfiles/rails_5.2.gemfile.lock +37 -83
- data/gemfiles/rails_6.0.gemfile.lock +37 -83
- data/lib/cloudtasker/backend/redis_task.rb +17 -9
- data/lib/cloudtasker/batch/job.rb +16 -6
- data/lib/cloudtasker/cron/schedule.rb +17 -8
- data/lib/cloudtasker/version.rb +1 -1
- data/lib/cloudtasker/worker.rb +45 -7
- data/lib/cloudtasker/worker_handler.rb +26 -0
- data/lib/cloudtasker.rb +0 -1
- metadata +8 -7
@@ -68,36 +68,16 @@ GEM
|
|
68
68
|
minitest (~> 5.1)
|
69
69
|
tzinfo (~> 1.1)
|
70
70
|
zeitwerk (~> 2.1, >= 2.1.8)
|
71
|
-
addressable (2.
|
71
|
+
addressable (2.7.0)
|
72
72
|
public_suffix (>= 2.0.2, < 5.0)
|
73
|
-
appraisal (2.4.
|
73
|
+
appraisal (2.4.0)
|
74
74
|
bundler
|
75
75
|
rake
|
76
76
|
thor (>= 0.14.0)
|
77
77
|
ast (2.4.2)
|
78
|
-
async (1.30.1)
|
79
|
-
console (~> 1.10)
|
80
|
-
nio4r (~> 2.3)
|
81
|
-
timers (~> 4.1)
|
82
|
-
async-http (0.56.5)
|
83
|
-
async (>= 1.25)
|
84
|
-
async-io (>= 1.28)
|
85
|
-
async-pool (>= 0.2)
|
86
|
-
protocol-http (~> 0.22.0)
|
87
|
-
protocol-http1 (~> 0.14.0)
|
88
|
-
protocol-http2 (~> 0.14.0)
|
89
|
-
async-http-faraday (0.11.0)
|
90
|
-
async-http (~> 0.42)
|
91
|
-
faraday
|
92
|
-
async-io (1.32.2)
|
93
|
-
async
|
94
|
-
async-pool (0.3.8)
|
95
|
-
async (>= 1.25)
|
96
78
|
builder (3.2.4)
|
97
|
-
concurrent-ruby (1.1.
|
98
|
-
connection_pool (2.2.
|
99
|
-
console (1.13.1)
|
100
|
-
fiber-local
|
79
|
+
concurrent-ruby (1.1.8)
|
80
|
+
connection_pool (2.2.3)
|
101
81
|
crack (0.4.5)
|
102
82
|
rexml
|
103
83
|
crass (1.0.6)
|
@@ -105,42 +85,26 @@ GEM
|
|
105
85
|
erubi (1.10.0)
|
106
86
|
et-orbi (1.2.4)
|
107
87
|
tzinfo
|
108
|
-
faraday (1.
|
109
|
-
faraday-em_http (~> 1.0)
|
110
|
-
faraday-em_synchrony (~> 1.0)
|
111
|
-
faraday-excon (~> 1.1)
|
112
|
-
faraday-httpclient (~> 1.0.1)
|
88
|
+
faraday (1.3.0)
|
113
89
|
faraday-net_http (~> 1.0)
|
114
|
-
faraday-net_http_persistent (~> 1.1)
|
115
|
-
faraday-patron (~> 1.0)
|
116
|
-
faraday-rack (~> 1.0)
|
117
90
|
multipart-post (>= 1.2, < 3)
|
118
|
-
ruby2_keywords
|
119
|
-
faraday-em_http (1.0.0)
|
120
|
-
faraday-em_synchrony (1.0.0)
|
121
|
-
faraday-excon (1.1.0)
|
91
|
+
ruby2_keywords
|
122
92
|
faraday-http-cache (2.2.0)
|
123
93
|
faraday (>= 0.8)
|
124
|
-
faraday-httpclient (1.0.1)
|
125
94
|
faraday-net_http (1.0.1)
|
126
|
-
|
127
|
-
faraday-patron (1.0.0)
|
128
|
-
faraday-rack (1.0.0)
|
129
|
-
fiber-local (1.0.0)
|
130
|
-
fugit (1.5.1)
|
95
|
+
fugit (1.4.2)
|
131
96
|
et-orbi (~> 1.1, >= 1.1.8)
|
132
97
|
raabro (~> 1.4)
|
133
|
-
github_changelog_generator (1.
|
98
|
+
github_changelog_generator (1.15.2)
|
134
99
|
activesupport
|
135
|
-
async (>= 1.25.0)
|
136
|
-
async-http-faraday
|
137
100
|
faraday-http-cache
|
138
101
|
multi_json
|
139
102
|
octokit (~> 4.6)
|
140
103
|
rainbow (>= 2.2.1)
|
141
104
|
rake (>= 10.0)
|
142
|
-
|
143
|
-
|
105
|
+
retriable (~> 3.0)
|
106
|
+
globalid (0.4.2)
|
107
|
+
activesupport (>= 4.2.0)
|
144
108
|
google-cloud-tasks (1.5.1)
|
145
109
|
google-gax (~> 1.8)
|
146
110
|
googleapis-common-protos (>= 1.3.9, < 2.0)
|
@@ -152,33 +116,33 @@ GEM
|
|
152
116
|
googleauth (~> 0.9)
|
153
117
|
grpc (~> 1.24)
|
154
118
|
rly (~> 0.2.3)
|
155
|
-
google-protobuf (3.
|
119
|
+
google-protobuf (3.15.5)
|
156
120
|
googleapis-common-protos (1.3.11)
|
157
121
|
google-protobuf (~> 3.14)
|
158
122
|
googleapis-common-protos-types (>= 1.0.6, < 2.0)
|
159
123
|
grpc (~> 1.27)
|
160
|
-
googleapis-common-protos-types (1.
|
124
|
+
googleapis-common-protos-types (1.0.6)
|
161
125
|
google-protobuf (~> 3.14)
|
162
|
-
googleauth (0.
|
126
|
+
googleauth (0.16.0)
|
163
127
|
faraday (>= 0.17.3, < 2.0)
|
164
128
|
jwt (>= 1.4, < 3.0)
|
165
129
|
memoist (~> 0.16)
|
166
130
|
multi_json (~> 1.11)
|
167
131
|
os (>= 0.9, < 2.0)
|
168
132
|
signet (~> 0.14)
|
169
|
-
grpc (1.
|
170
|
-
google-protobuf (~> 3.
|
133
|
+
grpc (1.36.0)
|
134
|
+
google-protobuf (~> 3.14)
|
171
135
|
googleapis-common-protos-types (~> 1.0)
|
172
136
|
grpc-google-iam-v1 (0.6.11)
|
173
137
|
google-protobuf (~> 3.14)
|
174
138
|
googleapis-common-protos (>= 1.3.11, < 2.0)
|
175
139
|
grpc (~> 1.27)
|
176
140
|
hashdiff (1.0.1)
|
177
|
-
i18n (1.8.
|
141
|
+
i18n (1.8.9)
|
178
142
|
concurrent-ruby (~> 1.0)
|
179
143
|
jaro_winkler (1.5.4)
|
180
|
-
jwt (2.2.
|
181
|
-
loofah (2.
|
144
|
+
jwt (2.2.2)
|
145
|
+
loofah (2.9.0)
|
182
146
|
crass (~> 1.0.2)
|
183
147
|
nokogiri (>= 1.5.9)
|
184
148
|
mail (2.7.1)
|
@@ -187,32 +151,23 @@ GEM
|
|
187
151
|
mimemagic (~> 0.3.2)
|
188
152
|
memoist (0.16.2)
|
189
153
|
method_source (1.0.0)
|
190
|
-
mimemagic (0.3.
|
191
|
-
|
192
|
-
|
193
|
-
mini_mime (1.1.1)
|
194
|
-
mini_portile2 (2.6.1)
|
154
|
+
mimemagic (0.3.5)
|
155
|
+
mini_mime (1.0.2)
|
156
|
+
mini_portile2 (2.5.0)
|
195
157
|
minitest (5.14.4)
|
196
158
|
multi_json (1.15.0)
|
197
159
|
multipart-post (2.1.1)
|
198
|
-
nio4r (2.5.
|
199
|
-
nokogiri (1.
|
200
|
-
mini_portile2 (~> 2.
|
160
|
+
nio4r (2.5.7)
|
161
|
+
nokogiri (1.11.2)
|
162
|
+
mini_portile2 (~> 2.5.0)
|
201
163
|
racc (~> 1.4)
|
202
|
-
octokit (4.
|
164
|
+
octokit (4.20.0)
|
203
165
|
faraday (>= 0.9)
|
204
166
|
sawyer (~> 0.8.0, >= 0.5.3)
|
205
167
|
os (1.1.1)
|
206
168
|
parallel (1.20.1)
|
207
|
-
parser (3.0.
|
169
|
+
parser (3.0.0.0)
|
208
170
|
ast (~> 2.4.1)
|
209
|
-
protocol-hpack (1.4.2)
|
210
|
-
protocol-http (0.22.5)
|
211
|
-
protocol-http1 (0.14.2)
|
212
|
-
protocol-http (~> 0.22)
|
213
|
-
protocol-http2 (0.14.2)
|
214
|
-
protocol-hpack (~> 1.4)
|
215
|
-
protocol-http (~> 0.18)
|
216
171
|
public_suffix (4.0.6)
|
217
172
|
raabro (1.4.0)
|
218
173
|
racc (1.5.2)
|
@@ -237,7 +192,7 @@ GEM
|
|
237
192
|
rails-dom-testing (2.0.3)
|
238
193
|
activesupport (>= 4.2.0)
|
239
194
|
nokogiri (>= 1.6)
|
240
|
-
rails-html-sanitizer (1.
|
195
|
+
rails-html-sanitizer (1.3.0)
|
241
196
|
loofah (~> 2.3)
|
242
197
|
railties (6.0.0)
|
243
198
|
actionpack (= 6.0.0)
|
@@ -246,10 +201,10 @@ GEM
|
|
246
201
|
rake (>= 0.8.7)
|
247
202
|
thor (>= 0.20.3, < 2.0)
|
248
203
|
rainbow (3.0.0)
|
249
|
-
rake (13.0.
|
250
|
-
redis (4.
|
204
|
+
rake (13.0.3)
|
205
|
+
redis (4.2.5)
|
251
206
|
retriable (3.1.2)
|
252
|
-
rexml (3.2.
|
207
|
+
rexml (3.2.4)
|
253
208
|
rly (0.2.3)
|
254
209
|
rspec (3.10.0)
|
255
210
|
rspec-core (~> 3.10.0)
|
@@ -264,7 +219,7 @@ GEM
|
|
264
219
|
rspec-mocks (3.10.2)
|
265
220
|
diff-lcs (>= 1.2.0, < 2.0)
|
266
221
|
rspec-support (~> 3.10.0)
|
267
|
-
rspec-rails (5.0.
|
222
|
+
rspec-rails (5.0.0)
|
268
223
|
actionpack (>= 5.2)
|
269
224
|
activesupport (>= 5.2)
|
270
225
|
railties (>= 5.2)
|
@@ -283,11 +238,11 @@ GEM
|
|
283
238
|
rubocop-rspec (1.37.0)
|
284
239
|
rubocop (>= 0.68.1)
|
285
240
|
ruby-progressbar (1.11.0)
|
286
|
-
ruby2_keywords (0.0.
|
241
|
+
ruby2_keywords (0.0.4)
|
287
242
|
sawyer (0.8.2)
|
288
243
|
addressable (>= 2.3.5)
|
289
244
|
faraday (> 0.8, < 2.0)
|
290
|
-
semantic_logger (4.
|
245
|
+
semantic_logger (4.7.4)
|
291
246
|
concurrent-ruby (~> 1.0)
|
292
247
|
signet (0.15.0)
|
293
248
|
addressable (~> 2.3)
|
@@ -305,15 +260,14 @@ GEM
|
|
305
260
|
thor (1.1.0)
|
306
261
|
thread_safe (0.3.6)
|
307
262
|
timecop (0.9.4)
|
308
|
-
timers (4.3.3)
|
309
263
|
tzinfo (1.2.9)
|
310
264
|
thread_safe (~> 0.1)
|
311
265
|
unicode-display_width (1.6.1)
|
312
|
-
webmock (3.
|
313
|
-
addressable (>= 2.
|
266
|
+
webmock (3.12.1)
|
267
|
+
addressable (>= 2.3.6)
|
314
268
|
crack (>= 0.3.2)
|
315
269
|
hashdiff (>= 0.4.0, < 2.0.0)
|
316
|
-
websocket-driver (0.7.
|
270
|
+
websocket-driver (0.7.3)
|
317
271
|
websocket-extensions (>= 0.1.0)
|
318
272
|
websocket-extensions (0.1.5)
|
319
273
|
zeitwerk (2.4.2)
|
@@ -23,14 +23,12 @@ module Cloudtasker
|
|
23
23
|
#
|
24
24
|
# Return a namespaced key.
|
25
25
|
#
|
26
|
-
# @param [String, Symbol] val The key to namespace
|
26
|
+
# @param [String, Symbol, nil] val The key to namespace
|
27
27
|
#
|
28
28
|
# @return [String] The namespaced key.
|
29
29
|
#
|
30
|
-
def self.key(val)
|
31
|
-
|
32
|
-
|
33
|
-
[to_s.underscore, val.to_s].join('/')
|
30
|
+
def self.key(val = nil)
|
31
|
+
[to_s.underscore, val].compact.map(&:to_s).join('/')
|
34
32
|
end
|
35
33
|
|
36
34
|
#
|
@@ -39,9 +37,17 @@ module Cloudtasker
|
|
39
37
|
# @return [Array<Cloudtasker::Backend::RedisTask>] All the tasks.
|
40
38
|
#
|
41
39
|
def self.all
|
42
|
-
redis.
|
43
|
-
|
44
|
-
|
40
|
+
if redis.exists?(key)
|
41
|
+
# Use Schedule Set if available
|
42
|
+
redis.smembers(key).map { |id| find(id) }
|
43
|
+
else
|
44
|
+
# Fallback to redis key matching and migrate tasks
|
45
|
+
# to use Task Set instead.
|
46
|
+
redis.search(key('*')).map do |gid|
|
47
|
+
task_id = gid.sub(key(''), '')
|
48
|
+
redis.sadd(key, task_id)
|
49
|
+
find(task_id)
|
50
|
+
end
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
@@ -82,6 +88,7 @@ module Cloudtasker
|
|
82
88
|
|
83
89
|
# Save job
|
84
90
|
redis.write(key(id), payload)
|
91
|
+
redis.sadd(key, id)
|
85
92
|
new(payload.merge(id: id))
|
86
93
|
end
|
87
94
|
|
@@ -105,6 +112,7 @@ module Cloudtasker
|
|
105
112
|
# @param [String] id The task id.
|
106
113
|
#
|
107
114
|
def self.delete(id)
|
115
|
+
redis.srem(key, id)
|
108
116
|
redis.del(key(id))
|
109
117
|
end
|
110
118
|
|
@@ -176,7 +184,7 @@ module Cloudtasker
|
|
176
184
|
# Remove the task from the queue.
|
177
185
|
#
|
178
186
|
def destroy
|
179
|
-
|
187
|
+
self.class.delete(id)
|
180
188
|
end
|
181
189
|
|
182
190
|
#
|
@@ -13,6 +13,10 @@ module Cloudtasker
|
|
13
13
|
# List of statuses triggering a completion callback
|
14
14
|
COMPLETION_STATUSES = %w[completed dead].freeze
|
15
15
|
|
16
|
+
# These callbacks do not need to raise errors on their own
|
17
|
+
# because the jobs will be either retried or dropped
|
18
|
+
IGNORED_ERRORED_CALLBACKS = %i[on_child_error on_child_dead].freeze
|
19
|
+
|
16
20
|
#
|
17
21
|
# Return the cloudtasker redis client
|
18
22
|
#
|
@@ -250,8 +254,8 @@ module Cloudtasker
|
|
250
254
|
end
|
251
255
|
|
252
256
|
#
|
253
|
-
# Run worker callback
|
254
|
-
#
|
257
|
+
# Run worker callback. The error and dead callbacks get
|
258
|
+
# silenced should they raise an error.
|
255
259
|
#
|
256
260
|
# @param [String, Symbol] callback The callback to run.
|
257
261
|
# @param [Array<any>] *args The callback arguments.
|
@@ -261,9 +265,15 @@ module Cloudtasker
|
|
261
265
|
def run_worker_callback(callback, *args)
|
262
266
|
worker.try(callback, *args)
|
263
267
|
rescue StandardError => e
|
264
|
-
|
265
|
-
|
266
|
-
|
268
|
+
# There is no point in retrying jobs due to failure callbacks failing
|
269
|
+
# Only completion callbacks will trigger a re-run of the job because
|
270
|
+
# these do matter for batch completion
|
271
|
+
raise(e) unless IGNORED_ERRORED_CALLBACKS.include?(callback)
|
272
|
+
|
273
|
+
# Log error instead
|
274
|
+
worker.logger.error(
|
275
|
+
["Callback #{callback} failed to run. Skipping to preserve error flow.", e, e.backtrace].flatten.join("\n")
|
276
|
+
)
|
267
277
|
end
|
268
278
|
|
269
279
|
#
|
@@ -275,7 +285,7 @@ module Cloudtasker
|
|
275
285
|
|
276
286
|
# Propagate event
|
277
287
|
parent_batch&.on_child_complete(self, status)
|
278
|
-
|
288
|
+
|
279
289
|
# The batch tree is complete. Cleanup the tree.
|
280
290
|
cleanup unless parent_batch
|
281
291
|
end
|
@@ -21,14 +21,12 @@ module Cloudtasker
|
|
21
21
|
#
|
22
22
|
# Return a namespaced key.
|
23
23
|
#
|
24
|
-
# @param [String, Symbol] val The key to namespace
|
24
|
+
# @param [String, Symbol, nil] val The key to namespace
|
25
25
|
#
|
26
26
|
# @return [String] The namespaced key.
|
27
27
|
#
|
28
|
-
def self.key(val)
|
29
|
-
|
30
|
-
|
31
|
-
[to_s.underscore, val.to_s].join('/')
|
28
|
+
def self.key(val = nil)
|
29
|
+
[to_s.underscore, val].compact.map(&:to_s).join('/')
|
32
30
|
end
|
33
31
|
|
34
32
|
#
|
@@ -37,8 +35,17 @@ module Cloudtasker
|
|
37
35
|
# @return [Array<Cloudtasker::Batch::Schedule>] The list of stored schedules.
|
38
36
|
#
|
39
37
|
def self.all
|
40
|
-
redis.
|
41
|
-
|
38
|
+
if redis.exists?(key)
|
39
|
+
# Use Schedule Set if available
|
40
|
+
redis.smembers(key).map { |id| find(id) }
|
41
|
+
else
|
42
|
+
# Fallback to redis key matching and migrate schedules
|
43
|
+
# to use Schedule Set instead.
|
44
|
+
redis.search(key('*')).map do |gid|
|
45
|
+
schedule_id = gid.sub(key(''), '')
|
46
|
+
redis.sadd(key, schedule_id)
|
47
|
+
find(schedule_id)
|
48
|
+
end
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
@@ -90,7 +97,7 @@ module Cloudtasker
|
|
90
97
|
end
|
91
98
|
|
92
99
|
#
|
93
|
-
#
|
100
|
+
# Delete a schedule by id.
|
94
101
|
#
|
95
102
|
# @param [String] id The schedule id.
|
96
103
|
#
|
@@ -101,6 +108,7 @@ module Cloudtasker
|
|
101
108
|
|
102
109
|
# Delete task and stored schedule
|
103
110
|
CloudTask.delete(schedule.task_id) if schedule.task_id
|
111
|
+
redis.srem(key, schedule.id)
|
104
112
|
redis.del(schedule.gid)
|
105
113
|
end
|
106
114
|
end
|
@@ -270,6 +278,7 @@ module Cloudtasker
|
|
270
278
|
|
271
279
|
# Save schedule
|
272
280
|
config_was_changed = config_changed?
|
281
|
+
redis.sadd(self.class.key, id)
|
273
282
|
redis.write(gid, to_h)
|
274
283
|
|
275
284
|
# Stop there if backend does not need update
|
data/lib/cloudtasker/version.rb
CHANGED
data/lib/cloudtasker/worker.rb
CHANGED
@@ -311,13 +311,25 @@ module Cloudtasker
|
|
311
311
|
end
|
312
312
|
|
313
313
|
#
|
314
|
-
# Return true if the job
|
315
|
-
#
|
314
|
+
# Return true if the job must declared dead upon raising
|
315
|
+
# an error.
|
316
|
+
#
|
317
|
+
# @return [Boolean] True if the job must die on error.
|
318
|
+
#
|
319
|
+
def job_must_die?
|
320
|
+
job_retries >= job_max_retries
|
321
|
+
end
|
322
|
+
|
323
|
+
#
|
324
|
+
# Return true if the job has strictly excceeded its maximum number
|
325
|
+
# of retries.
|
326
|
+
#
|
327
|
+
# Used a preemptive filter when running the job.
|
316
328
|
#
|
317
329
|
# @return [Boolean] True if the job is dead
|
318
330
|
#
|
319
331
|
def job_dead?
|
320
|
-
job_retries
|
332
|
+
job_retries > job_max_retries
|
321
333
|
end
|
322
334
|
|
323
335
|
#
|
@@ -332,11 +344,35 @@ module Cloudtasker
|
|
332
344
|
(perform_ended_at - perform_started_at).ceil(3)
|
333
345
|
end
|
334
346
|
|
347
|
+
#
|
348
|
+
# Run worker callback.
|
349
|
+
#
|
350
|
+
# @param [String, Symbol] callback The callback to run.
|
351
|
+
# @param [Array<any>] *args The callback arguments.
|
352
|
+
#
|
353
|
+
# @return [any] The callback return value
|
354
|
+
#
|
355
|
+
def run_callback(callback, *args)
|
356
|
+
try(callback, *args)
|
357
|
+
end
|
358
|
+
|
335
359
|
#=============================
|
336
360
|
# Private
|
337
361
|
#=============================
|
338
362
|
private
|
339
363
|
|
364
|
+
#
|
365
|
+
# Flag the worker as dead by invoking the on_dead hook
|
366
|
+
# and raising a DeadWorkerError
|
367
|
+
#
|
368
|
+
# @param [Exception, nil] error An optional exception to be passed to the DeadWorkerError.
|
369
|
+
#
|
370
|
+
def flag_as_dead(error = nil)
|
371
|
+
run_callback(:on_dead, error || DeadWorkerError.new)
|
372
|
+
ensure
|
373
|
+
raise(DeadWorkerError, error)
|
374
|
+
end
|
375
|
+
|
340
376
|
#
|
341
377
|
# Execute the worker perform method through the middleware chain.
|
342
378
|
#
|
@@ -346,6 +382,9 @@ module Cloudtasker
|
|
346
382
|
self.perform_started_at = Time.now
|
347
383
|
|
348
384
|
Cloudtasker.config.server_middleware.invoke(self) do
|
385
|
+
# Immediately abort the job if it is already dead
|
386
|
+
flag_as_dead if job_dead?
|
387
|
+
|
349
388
|
begin
|
350
389
|
# Abort if arguments are missing. This may happen with redis arguments storage
|
351
390
|
# if Cloud Tasks times out on a job but the job still succeeds
|
@@ -356,12 +395,11 @@ module Cloudtasker
|
|
356
395
|
# Perform the job
|
357
396
|
perform(*job_args)
|
358
397
|
rescue StandardError => e
|
359
|
-
|
360
|
-
return raise(e) unless
|
398
|
+
run_callback(:on_error, e)
|
399
|
+
return raise(e) unless job_must_die?
|
361
400
|
|
362
401
|
# Flag job as dead
|
363
|
-
|
364
|
-
raise(DeadWorkerError, e)
|
402
|
+
flag_as_dead(e)
|
365
403
|
end
|
366
404
|
end
|
367
405
|
ensure
|
@@ -45,6 +45,28 @@ module Cloudtasker
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
#
|
49
|
+
# Log error on execution failure.
|
50
|
+
#
|
51
|
+
# @param [Cloudtasker::Worker, nil] worker The worker.
|
52
|
+
# @param [Exception] error The error to log.
|
53
|
+
#
|
54
|
+
# @void
|
55
|
+
#
|
56
|
+
def self.log_execution_error(worker, error)
|
57
|
+
# ActiveJob has its own error logging. No need to double log the error.
|
58
|
+
# Note: we use string matching instead of class matching as
|
59
|
+
# ActiveJob::QueueAdapters::CloudtaskerAdapter::JobWrapper might not be loaded
|
60
|
+
return if worker.class.to_s =~ /^ActiveJob::/
|
61
|
+
|
62
|
+
# Choose logger to use based on context
|
63
|
+
# Worker will be nil on InvalidWorkerError - in that case we use generic logging
|
64
|
+
logger = worker&.logger || Cloudtasker.logger
|
65
|
+
|
66
|
+
# Log error
|
67
|
+
logger.error([error, error.backtrace].flatten.join("\n"))
|
68
|
+
end
|
69
|
+
|
48
70
|
#
|
49
71
|
# Execute a task worker from a task payload
|
50
72
|
#
|
@@ -88,6 +110,10 @@ module Cloudtasker
|
|
88
110
|
rescue DeadWorkerError, MissingWorkerArgumentsError => e
|
89
111
|
# Delete stored args payload if job is dead
|
90
112
|
redis.expire(args_payload_key, ARGS_PAYLOAD_CLEANUP_TTL) if args_payload_key
|
113
|
+
log_execution_error(worker, e)
|
114
|
+
raise(e)
|
115
|
+
rescue StandardError => e
|
116
|
+
log_execution_error(worker, e)
|
91
117
|
raise(e)
|
92
118
|
end
|
93
119
|
|
data/lib/cloudtasker.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudtasker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arnaud Lachaume
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -324,6 +324,7 @@ files:
|
|
324
324
|
- README.md
|
325
325
|
- Rakefile
|
326
326
|
- _config.yml
|
327
|
+
- app/controllers/cloudtasker/application_controller.rb
|
327
328
|
- app/controllers/cloudtasker/worker_controller.rb
|
328
329
|
- bin/console
|
329
330
|
- bin/setup
|
@@ -415,7 +416,7 @@ metadata:
|
|
415
416
|
homepage_uri: https://github.com/keypup-io/cloudtasker
|
416
417
|
source_code_uri: https://github.com/keypup-io/cloudtasker
|
417
418
|
changelog_uri: https://github.com/keypup-io/cloudtasker/master/tree/CHANGELOG.md
|
418
|
-
post_install_message:
|
419
|
+
post_install_message:
|
419
420
|
rdoc_options: []
|
420
421
|
require_paths:
|
421
422
|
- lib
|
@@ -426,12 +427,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
426
427
|
version: '0'
|
427
428
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
428
429
|
requirements:
|
429
|
-
- - "
|
430
|
+
- - ">"
|
430
431
|
- !ruby/object:Gem::Version
|
431
|
-
version:
|
432
|
+
version: 1.3.1
|
432
433
|
requirements: []
|
433
434
|
rubygems_version: 3.0.0
|
434
|
-
signing_key:
|
435
|
+
signing_key:
|
435
436
|
specification_version: 4
|
436
437
|
summary: Background jobs for Ruby using Google Cloud Tasks (beta)
|
437
438
|
test_files: []
|