cloudtasker 0.12.rc9 → 0.12.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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- cloudtasker (0.12.rc9)
4
+ cloudtasker (0.12.1)
5
5
  activesupport
6
6
  connection_pool
7
7
  fugit
@@ -68,35 +68,35 @@ GEM
68
68
  minitest (~> 5.1)
69
69
  tzinfo (~> 1.1)
70
70
  zeitwerk (~> 2.1, >= 2.1.8)
71
- addressable (2.7.0)
71
+ addressable (2.8.0)
72
72
  public_suffix (>= 2.0.2, < 5.0)
73
- appraisal (2.4.0)
73
+ appraisal (2.4.1)
74
74
  bundler
75
75
  rake
76
76
  thor (>= 0.14.0)
77
77
  ast (2.4.2)
78
- async (1.29.0)
78
+ async (1.30.1)
79
79
  console (~> 1.10)
80
80
  nio4r (~> 2.3)
81
81
  timers (~> 4.1)
82
- async-http (0.54.1)
83
- async (~> 1.25)
84
- async-io (~> 1.28)
85
- async-pool (~> 0.2)
86
- protocol-http (~> 0.21.0)
87
- protocol-http1 (~> 0.13.0)
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
88
  protocol-http2 (~> 0.14.0)
89
- async-http-faraday (0.9.0)
89
+ async-http-faraday (0.11.0)
90
90
  async-http (~> 0.42)
91
91
  faraday
92
- async-io (1.30.2)
93
- async (~> 1.14)
94
- async-pool (0.3.5)
95
- async (~> 1.25)
92
+ async-io (1.32.2)
93
+ async
94
+ async-pool (0.3.8)
95
+ async (>= 1.25)
96
96
  builder (3.2.4)
97
- concurrent-ruby (1.1.8)
97
+ concurrent-ruby (1.1.9)
98
98
  connection_pool (2.2.5)
99
- console (1.11.1)
99
+ console (1.13.1)
100
100
  fiber-local
101
101
  crack (0.4.5)
102
102
  rexml
@@ -105,22 +105,32 @@ GEM
105
105
  erubi (1.10.0)
106
106
  et-orbi (1.2.4)
107
107
  tzinfo
108
- faraday (1.4.1)
108
+ faraday (1.7.0)
109
+ faraday-em_http (~> 1.0)
110
+ faraday-em_synchrony (~> 1.0)
109
111
  faraday-excon (~> 1.1)
112
+ faraday-httpclient (~> 1.0.1)
110
113
  faraday-net_http (~> 1.0)
111
114
  faraday-net_http_persistent (~> 1.1)
115
+ faraday-patron (~> 1.0)
116
+ faraday-rack (~> 1.0)
112
117
  multipart-post (>= 1.2, < 3)
113
118
  ruby2_keywords (>= 0.0.4)
119
+ faraday-em_http (1.0.0)
120
+ faraday-em_synchrony (1.0.0)
114
121
  faraday-excon (1.1.0)
115
122
  faraday-http-cache (2.2.0)
116
123
  faraday (>= 0.8)
124
+ faraday-httpclient (1.0.1)
117
125
  faraday-net_http (1.0.1)
118
- faraday-net_http_persistent (1.1.0)
126
+ faraday-net_http_persistent (1.2.0)
127
+ faraday-patron (1.0.0)
128
+ faraday-rack (1.0.0)
119
129
  fiber-local (1.0.0)
120
- fugit (1.4.4)
130
+ fugit (1.5.1)
121
131
  et-orbi (~> 1.1, >= 1.1.8)
122
132
  raabro (~> 1.4)
123
- github_changelog_generator (1.16.1)
133
+ github_changelog_generator (1.16.4)
124
134
  activesupport
125
135
  async (>= 1.25.0)
126
136
  async-http-faraday
@@ -129,9 +139,8 @@ GEM
129
139
  octokit (~> 4.6)
130
140
  rainbow (>= 2.2.1)
131
141
  rake (>= 10.0)
132
- retriable (~> 3.0)
133
- globalid (0.4.2)
134
- activesupport (>= 4.2.0)
142
+ globalid (0.5.2)
143
+ activesupport (>= 5.0)
135
144
  google-cloud-tasks (1.5.1)
136
145
  google-gax (~> 1.8)
137
146
  googleapis-common-protos (>= 1.3.9, < 2.0)
@@ -143,21 +152,21 @@ GEM
143
152
  googleauth (~> 0.9)
144
153
  grpc (~> 1.24)
145
154
  rly (~> 0.2.3)
146
- google-protobuf (3.15.8)
155
+ google-protobuf (3.17.3)
147
156
  googleapis-common-protos (1.3.11)
148
157
  google-protobuf (~> 3.14)
149
158
  googleapis-common-protos-types (>= 1.0.6, < 2.0)
150
159
  grpc (~> 1.27)
151
- googleapis-common-protos-types (1.0.6)
160
+ googleapis-common-protos-types (1.1.0)
152
161
  google-protobuf (~> 3.14)
153
- googleauth (0.16.1)
162
+ googleauth (0.17.0)
154
163
  faraday (>= 0.17.3, < 2.0)
155
164
  jwt (>= 1.4, < 3.0)
156
165
  memoist (~> 0.16)
157
166
  multi_json (~> 1.11)
158
167
  os (>= 0.9, < 2.0)
159
168
  signet (~> 0.14)
160
- grpc (1.37.0)
169
+ grpc (1.38.0)
161
170
  google-protobuf (~> 3.15)
162
171
  googleapis-common-protos-types (~> 1.0)
163
172
  grpc-google-iam-v1 (0.6.11)
@@ -168,8 +177,8 @@ GEM
168
177
  i18n (1.8.10)
169
178
  concurrent-ruby (~> 1.0)
170
179
  jaro_winkler (1.5.4)
171
- jwt (2.2.2)
172
- loofah (2.9.1)
180
+ jwt (2.2.3)
181
+ loofah (2.12.0)
173
182
  crass (~> 1.0.2)
174
183
  nokogiri (>= 1.5.9)
175
184
  mail (2.7.1)
@@ -181,26 +190,26 @@ GEM
181
190
  mimemagic (0.3.10)
182
191
  nokogiri (~> 1)
183
192
  rake
184
- mini_mime (1.1.0)
185
- mini_portile2 (2.5.0)
193
+ mini_mime (1.1.1)
194
+ mini_portile2 (2.6.1)
186
195
  minitest (5.14.4)
187
196
  multi_json (1.15.0)
188
197
  multipart-post (2.1.1)
189
- nio4r (2.5.7)
190
- nokogiri (1.11.3)
191
- mini_portile2 (~> 2.5.0)
198
+ nio4r (2.5.8)
199
+ nokogiri (1.12.3)
200
+ mini_portile2 (~> 2.6.1)
192
201
  racc (~> 1.4)
193
- octokit (4.20.0)
202
+ octokit (4.21.0)
194
203
  faraday (>= 0.9)
195
204
  sawyer (~> 0.8.0, >= 0.5.3)
196
205
  os (1.1.1)
197
206
  parallel (1.20.1)
198
- parser (3.0.1.0)
207
+ parser (3.0.2.0)
199
208
  ast (~> 2.4.1)
200
209
  protocol-hpack (1.4.2)
201
- protocol-http (0.21.0)
202
- protocol-http1 (0.13.2)
203
- protocol-http (~> 0.19)
210
+ protocol-http (0.22.5)
211
+ protocol-http1 (0.14.2)
212
+ protocol-http (~> 0.22)
204
213
  protocol-http2 (0.14.2)
205
214
  protocol-hpack (~> 1.4)
206
215
  protocol-http (~> 0.18)
@@ -228,7 +237,7 @@ GEM
228
237
  rails-dom-testing (2.0.3)
229
238
  activesupport (>= 4.2.0)
230
239
  nokogiri (>= 1.6)
231
- rails-html-sanitizer (1.3.0)
240
+ rails-html-sanitizer (1.4.2)
232
241
  loofah (~> 2.3)
233
242
  railties (6.0.0)
234
243
  actionpack (= 6.0.0)
@@ -237,8 +246,8 @@ GEM
237
246
  rake (>= 0.8.7)
238
247
  thor (>= 0.20.3, < 2.0)
239
248
  rainbow (3.0.0)
240
- rake (13.0.3)
241
- redis (4.2.5)
249
+ rake (13.0.6)
250
+ redis (4.4.0)
242
251
  retriable (3.1.2)
243
252
  rexml (3.2.5)
244
253
  rly (0.2.3)
@@ -255,7 +264,7 @@ GEM
255
264
  rspec-mocks (3.10.2)
256
265
  diff-lcs (>= 1.2.0, < 2.0)
257
266
  rspec-support (~> 3.10.0)
258
- rspec-rails (5.0.1)
267
+ rspec-rails (5.0.2)
259
268
  actionpack (>= 5.2)
260
269
  activesupport (>= 5.2)
261
270
  railties (>= 5.2)
@@ -274,11 +283,11 @@ GEM
274
283
  rubocop-rspec (1.37.0)
275
284
  rubocop (>= 0.68.1)
276
285
  ruby-progressbar (1.11.0)
277
- ruby2_keywords (0.0.4)
286
+ ruby2_keywords (0.0.5)
278
287
  sawyer (0.8.2)
279
288
  addressable (>= 2.3.5)
280
289
  faraday (> 0.8, < 2.0)
281
- semantic_logger (4.7.4)
290
+ semantic_logger (4.8.2)
282
291
  concurrent-ruby (~> 1.0)
283
292
  signet (0.15.0)
284
293
  addressable (~> 2.3)
@@ -300,11 +309,11 @@ GEM
300
309
  tzinfo (1.2.9)
301
310
  thread_safe (~> 0.1)
302
311
  unicode-display_width (1.6.1)
303
- webmock (3.12.2)
304
- addressable (>= 2.3.6)
312
+ webmock (3.14.0)
313
+ addressable (>= 2.8.0)
305
314
  crack (>= 0.3.2)
306
315
  hashdiff (>= 0.4.0, < 2.0.0)
307
- websocket-driver (0.7.3)
316
+ websocket-driver (0.7.5)
308
317
  websocket-extensions (>= 0.1.0)
309
318
  websocket-extensions (0.1.5)
310
319
  zeitwerk (2.4.2)
@@ -330,4 +339,4 @@ DEPENDENCIES
330
339
  webmock
331
340
 
332
341
  BUNDLED WITH
333
- 2.2.9
342
+ 2.2.26
@@ -39,7 +39,7 @@ module Cloudtasker
39
39
  def self.all
40
40
  if redis.exists?(key)
41
41
  # Use Schedule Set if available
42
- redis.smembers(key).map { |id| find(id) }
42
+ redis.smembers(key).map { |id| find(id) }.compact
43
43
  else
44
44
  # Fallback to redis key matching and migrate tasks
45
45
  # to use Task Set instead.
@@ -6,7 +6,7 @@ module Cloudtasker
6
6
  # Include batch related methods onto Cloudtasker::Worker
7
7
  # See: Cloudtasker::Batch::Middleware#configure
8
8
  module Worker
9
- attr_accessor :batch
9
+ attr_accessor :batch, :parent_batch
10
10
  end
11
11
  end
12
12
  end
@@ -73,8 +73,12 @@ module Cloudtasker
73
73
  # Load extension if not loaded already on the worker class
74
74
  worker.class.include(Extension::Worker) unless worker.class <= Extension::Worker
75
75
 
76
- # Add batch capability
76
+ # Add batch and parent batch to worker
77
77
  worker.batch = new(worker)
78
+ worker.parent_batch = worker.batch.parent_batch
79
+
80
+ # Return the batch
81
+ worker.batch
78
82
  end
79
83
 
80
84
  #
@@ -259,9 +263,7 @@ module Cloudtasker
259
263
  migrate_batch_state_to_redis_hash
260
264
 
261
265
  # Update the batch state batch_id entry with the new status
262
- redis.with_lock("#{batch_state_gid}/#{batch_id}", max_wait: BATCH_MAX_LOCK_WAIT) do
263
- redis.hset(batch_state_gid, batch_id, status) if redis.hexists(batch_state_gid, batch_id)
264
- end
266
+ redis.hset(batch_state_gid, batch_id, status) if redis.hexists(batch_state_gid, batch_id)
265
267
  end
266
268
 
267
269
  #
@@ -273,10 +275,7 @@ module Cloudtasker
273
275
  migrate_batch_state_to_redis_hash
274
276
 
275
277
  # Check that all child jobs have completed
276
- redis.with_lock(batch_state_gid, max_wait: BATCH_MAX_LOCK_WAIT) do
277
- # Check that all children are complete
278
- redis.hvals(batch_state_gid).all? { |e| COMPLETION_STATUSES.include?(e) }
279
- end
278
+ redis.hvals(batch_state_gid).all? { |e| COMPLETION_STATUSES.include?(e) }
280
279
  end
281
280
 
282
281
  #
@@ -427,8 +426,11 @@ module Cloudtasker
427
426
  # Perform job
428
427
  yield
429
428
 
430
- # Save batch (if child workers have been enqueued)
431
- setup
429
+ # Save batch if child jobs added
430
+ setup if jobs.any?
431
+
432
+ # Save parent batch if batch expanded
433
+ parent_batch&.setup if parent_batch&.jobs&.any?
432
434
 
433
435
  # Complete batch
434
436
  complete(:completed)
@@ -7,7 +7,8 @@ module Cloudtasker
7
7
  class Config
8
8
  attr_accessor :redis, :store_payloads_in_redis
9
9
  attr_writer :secret, :gcp_location_id, :gcp_project_id,
10
- :gcp_queue_prefix, :processor_path, :logger, :mode, :max_retries, :dispatch_deadline
10
+ :gcp_queue_prefix, :processor_path, :logger, :mode, :max_retries,
11
+ :dispatch_deadline, :on_error, :on_dead
11
12
 
12
13
  # Max Cloud Task size in bytes
13
14
  MAX_TASK_SIZE = 100 * 1024 # 100 KB
@@ -51,6 +52,9 @@ module Cloudtasker
51
52
  MIN_DISPATCH_DEADLINE = 15 # seconds
52
53
  MAX_DISPATCH_DEADLINE = 30 * 60 # 30 minutes
53
54
 
55
+ # Default on_error Proc
56
+ DEFAULT_ON_ERROR = ->(error, worker) {}
57
+
54
58
  # The number of times jobs will be attempted before declaring them dead.
55
59
  #
56
60
  # With the default retry configuration (maxDoublings = 16 and minBackoff = 0.100s)
@@ -229,11 +233,31 @@ module Cloudtasker
229
233
  # @return [String] The cloudtasker secret
230
234
  #
231
235
  def secret
232
- @secret || (
236
+ @secret ||= (
233
237
  defined?(Rails) && Rails.application.credentials&.dig(:secret_key_base)
234
238
  ) || raise(StandardError, SECRET_MISSING_ERROR)
235
239
  end
236
240
 
241
+ #
242
+ # Return a Proc invoked whenever a worker runtime error is raised.
243
+ # See Cloudtasker::WorkerHandler.with_worker_handling
244
+ #
245
+ # @return [Proc] A Proc handler
246
+ #
247
+ def on_error
248
+ @on_error || DEFAULT_ON_ERROR
249
+ end
250
+
251
+ #
252
+ # Return a Proc invoked whenever a worker DeadWorkerError is raised.
253
+ # See Cloudtasker::WorkerHandler.with_worker_handling
254
+ #
255
+ # @return [Proc] A Proc handler
256
+ #
257
+ def on_dead
258
+ @on_dead || DEFAULT_ON_ERROR
259
+ end
260
+
237
261
  #
238
262
  # Return the chain of client middlewares.
239
263
  #
@@ -84,7 +84,7 @@ module Cloudtasker
84
84
 
85
85
  # Deliver task
86
86
  begin
87
- Thread.current['task'].deliver
87
+ Thread.current['task']&.deliver
88
88
  rescue Errno::EBADF, Errno::ECONNREFUSED => e
89
89
  raise(e) unless Thread.current['attempts'] < 3
90
90
 
@@ -149,25 +149,18 @@ module Cloudtasker
149
149
  # if taken by another job.
150
150
  #
151
151
  def lock!
152
- redis.with_lock(unique_gid) do
153
- locked_id = redis.get(unique_gid)
152
+ lock_acquired = redis.set(unique_gid, id, nx: true, ex: lock_ttl)
153
+ lock_already_acquired = !lock_acquired && redis.get(unique_gid) == id
154
154
 
155
- # Abort job lock process if lock is already taken by another job
156
- raise(LockError, locked_id) if locked_id && locked_id != id
157
-
158
- # Take job lock if the lock is currently free
159
- redis.set(unique_gid, id, ex: lock_ttl) unless locked_id
160
- end
155
+ raise(LockError) unless lock_acquired || lock_already_acquired
161
156
  end
162
157
 
163
158
  #
164
159
  # Delete the job lock.
165
160
  #
166
161
  def unlock!
167
- redis.with_lock(unique_gid) do
168
- locked_id = redis.get(unique_gid)
169
- redis.del(unique_gid) if locked_id == id
170
- end
162
+ locked_id = redis.get(unique_gid)
163
+ redis.del(unique_gid) if locked_id == id
171
164
  end
172
165
  end
173
166
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cloudtasker
4
- VERSION = '0.12.rc9'
4
+ VERSION = '0.12.1'
5
5
  end
@@ -102,9 +102,11 @@ module Cloudtasker
102
102
  # Delete stored args payload if job is dead
103
103
  redis.del(args_payload_key) if args_payload_key
104
104
  log_execution_error(worker, e)
105
+ Cloudtasker.config.on_dead.call(e, worker)
105
106
  raise(e)
106
107
  rescue StandardError => e
107
108
  log_execution_error(worker, e)
109
+ Cloudtasker.config.on_error.call(e, worker)
108
110
  raise(e)
109
111
  end
110
112
 
data/lib/cloudtasker.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/core_ext/string/inflections'
4
+ require 'active_support/core_ext/object/try'
4
5
 
5
6
  require 'cloudtasker/version'
6
7
  require 'cloudtasker/config'
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.12.rc9
4
+ version: 0.12.1
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-04-19 00:00:00.000000000 Z
11
+ date: 2021-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -324,7 +324,6 @@ files:
324
324
  - README.md
325
325
  - Rakefile
326
326
  - _config.yml
327
- - app/controllers/cloudtasker/application_controller.rb
328
327
  - app/controllers/cloudtasker/worker_controller.rb
329
328
  - bin/console
330
329
  - bin/setup
@@ -416,7 +415,7 @@ metadata:
416
415
  homepage_uri: https://github.com/keypup-io/cloudtasker
417
416
  source_code_uri: https://github.com/keypup-io/cloudtasker
418
417
  changelog_uri: https://github.com/keypup-io/cloudtasker/master/tree/CHANGELOG.md
419
- post_install_message:
418
+ post_install_message:
420
419
  rdoc_options: []
421
420
  require_paths:
422
421
  - lib
@@ -427,12 +426,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
427
426
  version: '0'
428
427
  required_rubygems_version: !ruby/object:Gem::Requirement
429
428
  requirements:
430
- - - ">"
429
+ - - ">="
431
430
  - !ruby/object:Gem::Version
432
- version: 1.3.1
431
+ version: '0'
433
432
  requirements: []
434
433
  rubygems_version: 3.0.0
435
- signing_key:
434
+ signing_key:
436
435
  specification_version: 4
437
436
  summary: Background jobs for Ruby using Google Cloud Tasks (beta)
438
437
  test_files: []