cloudtasker 0.13.1 → 0.14.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint_rubocop.yml +1 -1
  3. data/.github/workflows/test_ruby_3.x.yml +1 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +37 -9
  6. data/Appraisals +0 -12
  7. data/CHANGELOG.md +31 -0
  8. data/Gemfile +12 -0
  9. data/README.md +145 -6
  10. data/app/controllers/cloudtasker/worker_controller.rb +30 -9
  11. data/cloudtasker.gemspec +3 -10
  12. data/docs/CRON_JOBS.md +23 -0
  13. data/docs/STORABLE_JOBS.md +68 -0
  14. data/exe/cloudtasker +5 -2
  15. data/gemfiles/google_cloud_tasks_1.0.gemfile +10 -1
  16. data/gemfiles/google_cloud_tasks_1.1.gemfile +10 -1
  17. data/gemfiles/google_cloud_tasks_1.2.gemfile +10 -1
  18. data/gemfiles/google_cloud_tasks_1.3.gemfile +10 -1
  19. data/gemfiles/google_cloud_tasks_1.4.gemfile +10 -1
  20. data/gemfiles/google_cloud_tasks_1.5.gemfile +10 -1
  21. data/gemfiles/google_cloud_tasks_2.0.gemfile +10 -1
  22. data/gemfiles/google_cloud_tasks_2.1.gemfile +10 -1
  23. data/gemfiles/rails_5.2.gemfile +10 -0
  24. data/gemfiles/rails_6.0.gemfile +10 -0
  25. data/gemfiles/rails_6.1.gemfile +10 -0
  26. data/gemfiles/rails_7.0.gemfile +10 -0
  27. data/gemfiles/semantic_logger_3.4.gemfile +9 -1
  28. data/gemfiles/semantic_logger_4.6.gemfile +9 -1
  29. data/gemfiles/semantic_logger_4.7.0.gemfile +9 -1
  30. data/gemfiles/semantic_logger_4.7.2.gemfile +9 -1
  31. data/lib/active_job/queue_adapters/cloudtasker_adapter.rb +8 -1
  32. data/lib/cloudtasker/authenticator.rb +35 -0
  33. data/lib/cloudtasker/backend/google_cloud_task_v1.rb +2 -4
  34. data/lib/cloudtasker/backend/google_cloud_task_v2.rb +3 -5
  35. data/lib/cloudtasker/backend/memory_task.rb +8 -4
  36. data/lib/cloudtasker/backend/redis_task.rb +10 -4
  37. data/lib/cloudtasker/batch/batch_progress.rb +18 -14
  38. data/lib/cloudtasker/batch/job.rb +124 -31
  39. data/lib/cloudtasker/batch/middleware/server.rb +2 -2
  40. data/lib/cloudtasker/cli.rb +5 -7
  41. data/lib/cloudtasker/cloud_task.rb +16 -20
  42. data/lib/cloudtasker/config.rb +43 -10
  43. data/lib/cloudtasker/cron/middleware/server.rb +2 -2
  44. data/lib/cloudtasker/cron/schedule.rb +5 -2
  45. data/lib/cloudtasker/middleware/chain.rb +1 -1
  46. data/lib/cloudtasker/redis_client.rb +1 -4
  47. data/lib/cloudtasker/retry_worker_error.rb +6 -0
  48. data/lib/cloudtasker/storable/worker.rb +78 -0
  49. data/lib/cloudtasker/storable.rb +3 -0
  50. data/lib/cloudtasker/unique_job/conflict_strategy/base_strategy.rb +4 -2
  51. data/lib/cloudtasker/unique_job/lock/until_executed.rb +4 -4
  52. data/lib/cloudtasker/unique_job/lock/until_executing.rb +2 -2
  53. data/lib/cloudtasker/unique_job/lock/while_executing.rb +2 -2
  54. data/lib/cloudtasker/unique_job/middleware/client.rb +2 -2
  55. data/lib/cloudtasker/unique_job/middleware/server.rb +2 -2
  56. data/lib/cloudtasker/version.rb +1 -1
  57. data/lib/cloudtasker/worker.rb +38 -15
  58. data/lib/cloudtasker/worker_handler.rb +25 -19
  59. data/lib/cloudtasker/worker_logger.rb +48 -0
  60. data/lib/cloudtasker.rb +4 -1
  61. data/lib/tasks/setup_queue.rake +6 -6
  62. metadata +9 -145
  63. data/.github/workflows/test_ruby_2.6.yml +0 -37
@@ -10,11 +10,11 @@ module Cloudtasker
10
10
  # Acquire a lock for the job and trigger a conflict
11
11
  # if the lock could not be acquired.
12
12
  #
13
- def schedule
13
+ def schedule(&block)
14
14
  job.lock!
15
15
  yield
16
16
  rescue LockError
17
- conflict_instance.on_schedule { yield }
17
+ conflict_instance.on_schedule(&block)
18
18
  end
19
19
 
20
20
  #
@@ -10,11 +10,11 @@ module Cloudtasker
10
10
  # Acquire a lock for the job and trigger a conflict
11
11
  # if the lock could not be acquired.
12
12
  #
13
- def execute
13
+ def execute(&block)
14
14
  job.lock!
15
15
  yield
16
16
  rescue LockError
17
- conflict_instance.on_execute { yield }
17
+ conflict_instance.on_execute(&block)
18
18
  ensure
19
19
  # Unlock the job on any error to avoid deadlocks.
20
20
  job.unlock!
@@ -6,8 +6,8 @@ module Cloudtasker
6
6
  # TODO: kwargs to job otherwise it won't get the time_at
7
7
  # Client middleware, invoked when jobs are scheduled
8
8
  class Client
9
- def call(worker, _opts = {})
10
- Job.new(worker).lock_instance.schedule { yield }
9
+ def call(worker, _opts = {}, &block)
10
+ Job.new(worker).lock_instance.schedule(&block)
11
11
  end
12
12
  end
13
13
  end
@@ -5,8 +5,8 @@ module Cloudtasker
5
5
  module Middleware
6
6
  # Server middleware, invoked when jobs are executed
7
7
  class Server
8
- def call(worker, **_kwargs)
9
- Job.new(worker).lock_instance.execute { yield }
8
+ def call(worker, **_kwargs, &block)
9
+ Job.new(worker).lock_instance.execute(&block)
10
10
  end
11
11
  end
12
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cloudtasker
4
- VERSION = '0.13.1'
4
+ VERSION = '0.14.rc1'
5
5
  end
@@ -54,6 +54,15 @@ module Cloudtasker
54
54
 
55
55
  # Module class methods
56
56
  module ClassMethods
57
+ #
58
+ # Return the Cloudtasker redis client
59
+ #
60
+ # @return [Cloudtasker::RedisClient] The cloudtasker redis client.
61
+ #
62
+ def redis
63
+ @redis ||= RedisClient.new
64
+ end
65
+
57
66
  #
58
67
  # Set the worker runtime options.
59
68
  #
@@ -63,7 +72,7 @@ module Cloudtasker
63
72
  #
64
73
  def cloudtasker_options(opts = {})
65
74
  opt_list = opts&.map { |k, v| [k.to_sym, v] } || [] # symbolize
66
- @cloudtasker_options_hash = Hash[opt_list]
75
+ @cloudtasker_options_hash = opt_list.to_h
67
76
  end
68
77
 
69
78
  #
@@ -75,6 +84,17 @@ module Cloudtasker
75
84
  @cloudtasker_options_hash || {}
76
85
  end
77
86
 
87
+ #
88
+ # Return a namespaced cache key.
89
+ #
90
+ # @param [Any, Array<Any>, nil] val The key to namespace
91
+ #
92
+ # @return [String] The namespaced key(s).
93
+ #
94
+ def cache_key(val = nil)
95
+ [to_s.underscore, val].flatten.compact.map(&:to_s).join('/')
96
+ end
97
+
78
98
  #
79
99
  # Enqueue worker in the backgroundf.
80
100
  #
@@ -174,13 +194,13 @@ module Cloudtasker
174
194
  # @return [Integer] The value in seconds.
175
195
  #
176
196
  def dispatch_deadline
177
- @dispatch_deadline ||= [
178
- [
179
- Config::MIN_DISPATCH_DEADLINE,
180
- (self.class.cloudtasker_options_hash[:dispatch_deadline] || Cloudtasker.config.dispatch_deadline).to_i
181
- ].max,
182
- Config::MAX_DISPATCH_DEADLINE
183
- ].min
197
+ @dispatch_deadline ||= begin
198
+ configured_deadline = (
199
+ self.class.cloudtasker_options_hash[:dispatch_deadline] ||
200
+ Cloudtasker.config.dispatch_deadline
201
+ ).to_i
202
+ configured_deadline.clamp(Config::MIN_DISPATCH_DEADLINE, Config::MAX_DISPATCH_DEADLINE)
203
+ end
184
204
  end
185
205
 
186
206
  #
@@ -204,13 +224,16 @@ module Cloudtasker
204
224
  resp = execute_middleware_chain
205
225
 
206
226
  # Log job completion and return result
207
- logger.info("Job done after #{job_duration}s") { { duration: job_duration } }
227
+ logger.info("Job done after #{job_duration}s") { { duration: job_duration * 1000 } }
208
228
  resp
209
229
  rescue DeadWorkerError => e
210
- logger.info("Job dead after #{job_duration}s and #{job_retries} retries") { { duration: job_duration } }
230
+ logger.info("Job dead after #{job_duration}s and #{job_retries} retries") { { duration: job_duration * 1000 } }
231
+ raise(e)
232
+ rescue RetryWorkerError => e
233
+ logger.info("Job done after #{job_duration}s (retry requested)") { { duration: job_duration * 1000 } }
211
234
  raise(e)
212
235
  rescue StandardError => e
213
- logger.info("Job failed after #{job_duration}s") { { duration: job_duration } }
236
+ logger.info("Job failed after #{job_duration}s") { { duration: job_duration * 1000 } }
214
237
  raise(e)
215
238
  end
216
239
 
@@ -235,7 +258,7 @@ module Cloudtasker
235
258
  # @param [Integer] interval The delay in seconds.
236
259
  # @param [Time, Integer] interval The time at which the job should run
237
260
  #
238
- # @return [Cloudtasker::CloudTask] The Google Task response
261
+ # @return [Cloudtasker::CloudTask, nil] The Google Task response or nil if the job was not scheduled
239
262
  #
240
263
  def schedule(**args)
241
264
  # Evaluate when to schedule the job
@@ -323,7 +346,7 @@ module Cloudtasker
323
346
  # @return [Integer] The number of retries
324
347
  #
325
348
  def job_max_retries
326
- @job_max_retries ||= (try(:max_retries, *job_args) || self.class.max_retries)
349
+ @job_max_retries ||= try(:max_retries, *job_args) || self.class.max_retries
327
350
  end
328
351
 
329
352
  #
@@ -373,7 +396,7 @@ module Cloudtasker
373
396
  def job_duration
374
397
  return 0.0 unless perform_ended_at && perform_started_at
375
398
 
376
- (perform_ended_at - perform_started_at).ceil(3)
399
+ @job_duration ||= (perform_ended_at - perform_started_at).ceil(3)
377
400
  end
378
401
 
379
402
  #
@@ -422,7 +445,7 @@ module Cloudtasker
422
445
  # Perform the job
423
446
  perform(*job_args)
424
447
  rescue StandardError => e
425
- run_callback(:on_error, e)
448
+ run_callback(:on_error, e) unless e.is_a?(RetryWorkerError)
426
449
  return raise(e) unless job_must_die?
427
450
 
428
451
  # Flag job as dead
@@ -53,6 +53,9 @@ module Cloudtasker
53
53
  # ActiveJob::QueueAdapters::CloudtaskerAdapter::JobWrapper might not be loaded
54
54
  return if worker.class.to_s =~ /^ActiveJob::/
55
55
 
56
+ # Do not log error when a retry was specifically requested
57
+ return if error.is_a?(RetryWorkerError)
58
+
56
59
  # Choose logger to use based on context
57
60
  # Worker will be nil on InvalidWorkerError - in that case we use generic logging
58
61
  logger = worker&.logger || Cloudtasker.logger
@@ -148,16 +151,21 @@ module Cloudtasker
148
151
  # @return [Hash] The task body
149
152
  #
150
153
  def task_payload
154
+ # Generate content
155
+ worker_payload_json = worker_payload.to_json
156
+
157
+ # Build payload
151
158
  {
152
159
  http_request: {
153
160
  http_method: 'POST',
154
161
  url: Cloudtasker.config.processor_url,
155
162
  headers: {
156
163
  Cloudtasker::Config::CONTENT_TYPE_HEADER => 'application/json',
157
- Cloudtasker::Config::AUTHORIZATION_HEADER => "Bearer #{Authenticator.verification_token}"
158
- },
159
- body: worker_payload.to_json
160
- },
164
+ Cloudtasker::Config::CT_SIGNATURE_HEADER => Authenticator.sign_payload(worker_payload_json)
165
+ }.compact,
166
+ oidc_token: Cloudtasker.config.oidc,
167
+ body: worker_payload_json
168
+ }.compact,
161
169
  dispatch_deadline: worker.dispatch_deadline.to_i,
162
170
  queue: worker.job_queue
163
171
  }
@@ -187,21 +195,19 @@ module Cloudtasker
187
195
  # @return [Hash] The worker args payload.
188
196
  #
189
197
  def worker_args_payload
190
- @worker_args_payload ||= begin
191
- if store_payload_in_redis?
192
- # Store payload in Redis
193
- self.class.redis.write(
194
- self.class.key([REDIS_PAYLOAD_NAMESPACE, worker.job_id].join('/')),
195
- worker.job_args
196
- )
197
-
198
- # Return reference to args payload
199
- { job_args_payload_id: worker.job_id }
200
- else
201
- # Return regular job args payload
202
- { job_args: worker.job_args }
203
- end
204
- end
198
+ @worker_args_payload ||= if store_payload_in_redis?
199
+ # Store payload in Redis
200
+ self.class.redis.write(
201
+ self.class.key([REDIS_PAYLOAD_NAMESPACE, worker.job_id].join('/')),
202
+ worker.job_args
203
+ )
204
+
205
+ # Return reference to args payload
206
+ { job_args_payload_id: worker.job_id }
207
+ else
208
+ # Return regular job args payload
209
+ { job_args: worker.job_args }
210
+ end
205
211
  end
206
212
 
207
213
  #
@@ -8,6 +8,54 @@ module Cloudtasker
8
8
 
9
9
  class << self
10
10
  attr_accessor :log_context_processor
11
+
12
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
13
+ #
14
+ # Truncate an array or hash payload.
15
+ #
16
+ # This can be used to log arguments on jobs while still keeping logs to a
17
+ # reasonable size.
18
+ #
19
+ # @param [Hash,Array] payload The payload to truncate
20
+ # @param [Integer] string_limit The maximum size for strings. Set to -1 to disable.
21
+ # @param [Integer] array_limit The maximum length for arrays. Set to -1 to disable.
22
+ # @param [Hash] max_depth The maximum recursive depth. Set to -1 to disable.
23
+ #
24
+ # @return [Hash,Array] The truncated payload
25
+ #
26
+ def truncate(payload, **kwargs)
27
+ depth = kwargs[:depth].to_i
28
+ max_depth = kwargs[:max_depth] || 3
29
+ string_limit = kwargs[:string_limit] || 64
30
+ array_limit = kwargs[:array_limit] || 10
31
+
32
+ case payload
33
+ when Array
34
+ if max_depth > -1 && depth > max_depth
35
+ ["...#{payload.size} items..."]
36
+ elsif array_limit > -1
37
+ payload.take(array_limit).map { |e| truncate(e, **kwargs, depth: depth + 1) } +
38
+ (payload.size > array_limit ? ["...#{payload.size - array_limit} items..."] : [])
39
+ else
40
+ payload.map { |e| truncate(e, **kwargs, depth: depth + 1) }
41
+ end
42
+ when Hash
43
+ if max_depth > -1 && depth > max_depth
44
+ '{hash}'
45
+ else
46
+ payload.transform_values { |e| truncate(e, **kwargs, depth: depth + 1) }
47
+ end
48
+ when String
49
+ if string_limit > -1 && payload.size > string_limit
50
+ payload.truncate(string_limit)
51
+ else
52
+ payload
53
+ end
54
+ else
55
+ payload
56
+ end
57
+ end
58
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
11
59
  end
12
60
 
13
61
  # Only log the job meta information by default (exclude arguments)
data/lib/cloudtasker.rb CHANGED
@@ -3,12 +3,15 @@
3
3
  require 'active_support/core_ext/object/blank'
4
4
  require 'active_support/core_ext/object/try'
5
5
  require 'active_support/core_ext/string/inflections'
6
+ require 'active_support/core_ext/string/filters'
7
+ require 'active_support/security_utils'
6
8
 
7
9
  require 'cloudtasker/version'
8
10
  require 'cloudtasker/config'
9
11
 
10
12
  require 'cloudtasker/authentication_error'
11
13
  require 'cloudtasker/dead_worker_error'
14
+ require 'cloudtasker/retry_worker_error'
12
15
  require 'cloudtasker/invalid_worker_error'
13
16
  require 'cloudtasker/missing_worker_arguments_error'
14
17
  require 'cloudtasker/max_task_size_exceeded_error'
@@ -51,4 +54,4 @@ module Cloudtasker
51
54
  end
52
55
  end
53
56
 
54
- require 'cloudtasker/engine' if defined?(::Rails::Engine)
57
+ require 'cloudtasker/engine' if defined?(Rails::Engine)
@@ -7,14 +7,14 @@ ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] ||= 'true'
7
7
 
8
8
  namespace :cloudtasker do
9
9
  desc 'Setup a Cloud Task queue. (default options: ' \
10
- "name=#{Cloudtasker::Config::DEFAULT_JOB_QUEUE}, " \
11
- "concurrency=#{Cloudtasker::Config::DEFAULT_QUEUE_CONCURRENCY}, " \
12
- "retries=#{Cloudtasker::Config::DEFAULT_QUEUE_RETRIES})"
10
+ "name=#{Cloudtasker::Config::DEFAULT_JOB_QUEUE}, " \
11
+ "concurrency=#{Cloudtasker::Config::DEFAULT_QUEUE_CONCURRENCY}, " \
12
+ "retries=#{Cloudtasker::Config::DEFAULT_QUEUE_RETRIES})"
13
13
  task setup_queue: :environment do
14
14
  puts Cloudtasker::CloudTask.setup_production_queue(
15
- name: ENV['name'],
16
- concurrency: ENV['concurrency'],
17
- retries: ENV['retries']
15
+ name: ENV.fetch('name', nil),
16
+ concurrency: ENV.fetch('concurrency', nil),
17
+ retries: ENV.fetch('retries', nil)
18
18
  )
19
19
  end
20
20
  end
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.13.1
4
+ version: 0.14.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-19 00:00:00.000000000 Z
11
+ date: 2024-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,146 +108,6 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: appraisal
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: bundler
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '2.0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '2.0'
139
- - !ruby/object:Gem::Dependency
140
- name: rake
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: 12.3.3
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: 12.3.3
153
- - !ruby/object:Gem::Dependency
154
- name: rspec
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '3.0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '3.0'
167
- - !ruby/object:Gem::Dependency
168
- name: rspec-json_expectations
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: '2.2'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: '2.2'
181
- - !ruby/object:Gem::Dependency
182
- name: rubocop
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - '='
186
- - !ruby/object:Gem::Version
187
- version: 0.76.0
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - '='
193
- - !ruby/object:Gem::Version
194
- version: 0.76.0
195
- - !ruby/object:Gem::Dependency
196
- name: rubocop-rspec
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - '='
200
- - !ruby/object:Gem::Version
201
- version: 1.37.0
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - '='
207
- - !ruby/object:Gem::Version
208
- version: 1.37.0
209
- - !ruby/object:Gem::Dependency
210
- name: semantic_logger
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
- - !ruby/object:Gem::Dependency
224
- name: timecop
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - ">="
228
- - !ruby/object:Gem::Version
229
- version: '0'
230
- type: :development
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - ">="
235
- - !ruby/object:Gem::Version
236
- version: '0'
237
- - !ruby/object:Gem::Dependency
238
- name: webmock
239
- requirement: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - ">="
242
- - !ruby/object:Gem::Version
243
- version: '0'
244
- type: :development
245
- prerelease: false
246
- version_requirements: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - ">="
249
- - !ruby/object:Gem::Version
250
- version: '0'
251
111
  description: Background jobs for Ruby using Google Cloud Tasks (beta)
252
112
  email:
253
113
  - arnaud.lachaume@keypup.io
@@ -257,7 +117,6 @@ extensions: []
257
117
  extra_rdoc_files: []
258
118
  files:
259
119
  - ".github/workflows/lint_rubocop.yml"
260
- - ".github/workflows/test_ruby_2.6.yml"
261
120
  - ".github/workflows/test_ruby_2.7.yml"
262
121
  - ".github/workflows/test_ruby_3.x.yml"
263
122
  - ".gitignore"
@@ -278,6 +137,7 @@ files:
278
137
  - config/routes.rb
279
138
  - docs/BATCH_JOBS.md
280
139
  - docs/CRON_JOBS.md
140
+ - docs/STORABLE_JOBS.md
281
141
  - docs/UNIQUE_JOBS.md
282
142
  - exe/cloudtasker
283
143
  - gemfiles/.bundle/config
@@ -328,6 +188,9 @@ files:
328
188
  - lib/cloudtasker/middleware/chain.rb
329
189
  - lib/cloudtasker/missing_worker_arguments_error.rb
330
190
  - lib/cloudtasker/redis_client.rb
191
+ - lib/cloudtasker/retry_worker_error.rb
192
+ - lib/cloudtasker/storable.rb
193
+ - lib/cloudtasker/storable/worker.rb
331
194
  - lib/cloudtasker/testing.rb
332
195
  - lib/cloudtasker/unique_job.rb
333
196
  - lib/cloudtasker/unique_job/conflict_strategy/base_strategy.rb
@@ -357,6 +220,7 @@ metadata:
357
220
  homepage_uri: https://github.com/keypup-io/cloudtasker
358
221
  source_code_uri: https://github.com/keypup-io/cloudtasker
359
222
  changelog_uri: https://github.com/keypup-io/cloudtasker/master/tree/CHANGELOG.md
223
+ rubygems_mfa_required: 'true'
360
224
  post_install_message:
361
225
  rdoc_options: []
362
226
  require_paths:
@@ -365,14 +229,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
365
229
  requirements:
366
230
  - - ">="
367
231
  - !ruby/object:Gem::Version
368
- version: '0'
232
+ version: 2.7.0
369
233
  required_rubygems_version: !ruby/object:Gem::Requirement
370
234
  requirements:
371
235
  - - ">="
372
236
  - !ruby/object:Gem::Version
373
237
  version: '0'
374
238
  requirements: []
375
- rubygems_version: 3.4.8
239
+ rubygems_version: 3.5.4
376
240
  signing_key:
377
241
  specification_version: 4
378
242
  summary: Background jobs for Ruby using Google Cloud Tasks (beta)
@@ -1,37 +0,0 @@
1
- name: Ruby 2.6
2
-
3
- on: [push, pull_request]
4
-
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
- strategy:
9
- matrix:
10
- ruby:
11
- - '2.6'
12
- appraisal:
13
- - 'google_cloud_tasks_1.0'
14
- - 'google_cloud_tasks_1.1'
15
- - 'google_cloud_tasks_1.2'
16
- - 'google_cloud_tasks_1.3'
17
- - 'google_cloud_tasks_1.4'
18
- - 'google_cloud_tasks_1.5'
19
- - 'google_cloud_tasks_2.0'
20
- - 'google_cloud_tasks_2.1'
21
- - 'rails_5.2'
22
- - 'rails_6.0'
23
- - 'rails_6.1'
24
- - 'semantic_logger_3.4'
25
- - 'semantic_logger_4.6'
26
- - 'semantic_logger_4.7.0'
27
- - 'semantic_logger_4.7.2'
28
- env:
29
- BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.appraisal }}.gemfile
30
- steps:
31
- - uses: actions/checkout@v2
32
- - uses: zhulik/redis-action@1.1.0
33
- - uses: ruby/setup-ruby@v1
34
- with:
35
- ruby-version: ${{ matrix.ruby }}
36
- bundler-cache: true
37
- - run: bundle exec rspec