cloudtasker 0.2.0 → 0.3.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +5 -0
  4. data/.travis.yml +10 -1
  5. data/Appraisals +25 -0
  6. data/Gemfile.lock +10 -4
  7. data/README.md +550 -4
  8. data/app/controllers/cloudtasker/application_controller.rb +2 -0
  9. data/app/controllers/cloudtasker/worker_controller.rb +22 -2
  10. data/cloudtasker.gemspec +4 -3
  11. data/docs/BATCH_JOBS.md +66 -0
  12. data/docs/CRON_JOBS.md +63 -0
  13. data/docs/UNIQUE_JOBS.md +127 -0
  14. data/exe/cloudtasker +15 -0
  15. data/gemfiles/.bundle/config +2 -0
  16. data/gemfiles/google_cloud_tasks_1.0.gemfile +9 -0
  17. data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +263 -0
  18. data/gemfiles/google_cloud_tasks_1.1.gemfile +9 -0
  19. data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +263 -0
  20. data/gemfiles/google_cloud_tasks_1.2.gemfile +9 -0
  21. data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +263 -0
  22. data/gemfiles/google_cloud_tasks_1.3.gemfile +9 -0
  23. data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +264 -0
  24. data/gemfiles/rails_4.0.gemfile +10 -0
  25. data/gemfiles/rails_4.1.gemfile +9 -0
  26. data/gemfiles/rails_4.2.gemfile +9 -0
  27. data/gemfiles/rails_5.0.gemfile +9 -0
  28. data/gemfiles/rails_5.1.gemfile +9 -0
  29. data/gemfiles/rails_5.2.gemfile +9 -0
  30. data/gemfiles/rails_5.2.gemfile.lock +247 -0
  31. data/gemfiles/rails_6.0.gemfile +9 -0
  32. data/gemfiles/rails_6.0.gemfile.lock +263 -0
  33. data/lib/cloudtasker.rb +19 -1
  34. data/lib/cloudtasker/backend/google_cloud_task.rb +139 -0
  35. data/lib/cloudtasker/backend/memory_task.rb +190 -0
  36. data/lib/cloudtasker/backend/redis_task.rb +248 -0
  37. data/lib/cloudtasker/batch/batch_progress.rb +19 -1
  38. data/lib/cloudtasker/batch/job.rb +81 -20
  39. data/lib/cloudtasker/cli.rb +194 -0
  40. data/lib/cloudtasker/cloud_task.rb +91 -0
  41. data/lib/cloudtasker/config.rb +64 -2
  42. data/lib/cloudtasker/cron/job.rb +2 -2
  43. data/lib/cloudtasker/cron/schedule.rb +15 -5
  44. data/lib/cloudtasker/dead_worker_error.rb +6 -0
  45. data/lib/cloudtasker/local_server.rb +74 -0
  46. data/lib/cloudtasker/railtie.rb +10 -0
  47. data/lib/cloudtasker/testing.rb +133 -0
  48. data/lib/cloudtasker/unique_job/job.rb +1 -1
  49. data/lib/cloudtasker/unique_job/lock/base_lock.rb +1 -1
  50. data/lib/cloudtasker/unique_job/lock/until_executed.rb +3 -1
  51. data/lib/cloudtasker/unique_job/lock/while_executing.rb +3 -1
  52. data/lib/cloudtasker/version.rb +1 -1
  53. data/lib/cloudtasker/worker.rb +59 -16
  54. data/lib/cloudtasker/{task.rb → worker_handler.rb} +10 -77
  55. data/lib/cloudtasker/worker_logger.rb +155 -0
  56. data/lib/tasks/setup_queue.rake +10 -0
  57. metadata +55 -6
@@ -3,39 +3,13 @@
3
3
  require 'google/cloud/tasks'
4
4
 
5
5
  module Cloudtasker
6
- # Build, serialize and schedule tasks on GCP Cloud Task
7
- class Task
6
+ # Build, serialize and schedule tasks on the processing backend.
7
+ class WorkerHandler
8
8
  attr_reader :worker, :job_args
9
9
 
10
10
  # Alrogith used to sign the verification token
11
11
  JWT_ALG = 'HS256'
12
12
 
13
- # TODO: Move to a dedicated CloudTask class
14
- #
15
- # Find a Cloud task
16
- #
17
- # @param [String] id The ID of the task.
18
- #
19
- # @return [Google::Cloud::Tasks::V2beta3::Task] The cloud task.
20
- #
21
- def self.find(id)
22
- client.get_task(id)
23
- rescue Google::Gax::RetryError
24
- nil
25
- end
26
-
27
- # TODO: Move to a dedicated CloudTask class
28
- #
29
- # Delete a Cloud task
30
- #
31
- # @param [String] id The ID of the task.
32
- #
33
- def self.delete(id)
34
- client.delete_task(id)
35
- rescue Google::Gax::RetryError
36
- nil
37
- end
38
-
39
13
  #
40
14
  # Execute a task worker from a task payload
41
15
  #
@@ -48,15 +22,6 @@ module Cloudtasker
48
22
  worker.execute
49
23
  end
50
24
 
51
- #
52
- # Return the Google Cloud Task client.
53
- #
54
- # @return [Google::Cloud::Tasks] The Google Cloud Task client.
55
- #
56
- def self.client
57
- @client ||= ::Google::Cloud::Tasks.new(version: :v2beta3)
58
- end
59
-
60
25
  #
61
26
  # Prepare a new cloud task.
62
27
  #
@@ -66,37 +31,6 @@ module Cloudtasker
66
31
  @worker = worker
67
32
  end
68
33
 
69
- #
70
- # Return the Google Cloud Task client.
71
- #
72
- # @return [Google::Cloud::Tasks] The Google Cloud Task client.
73
- #
74
- def client
75
- self.class.client
76
- end
77
-
78
- #
79
- # Return the cloudtasker configuration. See Cloudtasker#configure.
80
- #
81
- # @return [Cloudtasker::Config] The library configuration.
82
- #
83
- def config
84
- Cloudtasker.config
85
- end
86
-
87
- #
88
- # Return the fully qualified path for the Cloud Task queue.
89
- #
90
- # @return [String] The queue path.
91
- #
92
- def queue_path
93
- client.queue_path(
94
- config.gcp_project_id,
95
- config.gcp_location_id,
96
- config.gcp_queue_id
97
- )
98
- end
99
-
100
34
  #
101
35
  # Return the full task configuration sent to Cloud Task
102
36
  #
@@ -106,7 +40,7 @@ module Cloudtasker
106
40
  {
107
41
  http_request: {
108
42
  http_method: 'POST',
109
- url: config.processor_url,
43
+ url: Cloudtasker.config.processor_url,
110
44
  headers: {
111
45
  'Content-Type' => 'application/json',
112
46
  'Authorization' => "Bearer #{Authenticator.verification_token}"
@@ -133,7 +67,7 @@ module Cloudtasker
133
67
  worker: worker.class.to_s,
134
68
  job_id: worker.job_id,
135
69
  job_args: worker.job_args,
136
- job_meta: worker.job_meta
70
+ job_meta: worker.job_meta.to_h
137
71
  }
138
72
  end
139
73
 
@@ -142,16 +76,15 @@ module Cloudtasker
142
76
  # before running a task.
143
77
  #
144
78
  # @param [Integer, nil] interval The time to wait.
79
+ # @param [Integer, nil] time_at The time at which the job should run.
145
80
  #
146
- # @return [Google::Protobuf::Timestamp, nil] The protobuff timestamp
81
+ # @return [Integer, nil] The Unix timestamp.
147
82
  #
148
83
  def schedule_time(interval: nil, time_at: nil)
149
84
  return nil unless interval || time_at
150
85
 
151
- # Generate protobuf timestamp
152
- timestamp = Google::Protobuf::Timestamp.new
153
- timestamp.seconds = (time_at || Time.now).to_i + interval.to_i
154
- timestamp
86
+ # Generate the complete Unix timestamp
87
+ (time_at || Time.now).to_i + interval.to_i
155
88
  end
156
89
 
157
90
  #
@@ -160,7 +93,7 @@ module Cloudtasker
160
93
  # @param [Integer, nil] interval How to wait before running the task.
161
94
  # Leave to `nil` to run now.
162
95
  #
163
- # @return [Google::Cloud::Tasks::V2beta3::Task] The Google Task response
96
+ # @return [Cloudtasker::CloudTask] The Google Task response
164
97
  #
165
98
  def schedule(interval: nil, time_at: nil)
166
99
  # Generate task payload
@@ -169,7 +102,7 @@ module Cloudtasker
169
102
  ).compact
170
103
 
171
104
  # Create and return remote task
172
- client.create_task(queue_path, task)
105
+ CloudTask.create(task)
173
106
  end
174
107
  end
175
108
  end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cloudtasker
4
+ # Add contextual information to logs generated
5
+ # by workers
6
+ class WorkerLogger
7
+ attr_accessor :worker
8
+
9
+ class << self
10
+ attr_accessor :log_context_processor
11
+ end
12
+
13
+ # Only log the job meta information by default (exclude arguments)
14
+ DEFAULT_CONTEXT_PROCESSOR = ->(worker) { worker.to_h.slice(:worker, :job_id, :job_meta) }
15
+
16
+ #
17
+ # Build a new instance of the class.
18
+ #
19
+ # @param [Cloudtasker::Worker] worker The worker.
20
+ #
21
+ def initialize(worker)
22
+ @worker = worker
23
+ end
24
+
25
+ #
26
+ # Return the Proc responsible for formatting the log payload.
27
+ #
28
+ # @return [Proc] The context processor.
29
+ #
30
+ def context_processor
31
+ @context_processor ||= worker.class.cloudtasker_options_hash[:log_context_processor] ||
32
+ self.class.log_context_processor ||
33
+ DEFAULT_CONTEXT_PROCESSOR
34
+ end
35
+
36
+ #
37
+ # The block to pass to log messages.
38
+ #
39
+ # @return [Proc] The log block.
40
+ #
41
+ def log_block
42
+ @log_block ||= proc { context_processor.call(worker) }
43
+ end
44
+
45
+ #
46
+ # Return the Cloudtasker logger.
47
+ #
48
+ # @return [Logger, any] The cloudtasker logger.
49
+ #
50
+ def logger
51
+ Cloudtasker.logger
52
+ end
53
+
54
+ #
55
+ # Format main log message.
56
+ #
57
+ # @param [String] msg The message to log.
58
+ #
59
+ # @return [String] The formatted log message
60
+ #
61
+ def formatted_message(msg)
62
+ "[Cloudtasker][#{worker.job_id}] #{msg}"
63
+ end
64
+
65
+ #
66
+ # Log an info message.
67
+ #
68
+ # @param [String] msg The message to log.
69
+ # @param [Proc] &block Optional context block.
70
+ #
71
+ def info(msg, &block)
72
+ log_message(:info, msg, &block)
73
+ end
74
+
75
+ #
76
+ # Log an error message.
77
+ #
78
+ # @param [String] msg The message to log.
79
+ # @param [Proc] &block Optional context block.
80
+ #
81
+ def error(msg, &block)
82
+ log_message(:error, msg, &block)
83
+ end
84
+
85
+ #
86
+ # Log an fatal message.
87
+ #
88
+ # @param [String] msg The message to log.
89
+ # @param [Proc] &block Optional context block.
90
+ #
91
+ def fatal(msg, &block)
92
+ log_message(:fatal, msg, &block)
93
+ end
94
+
95
+ #
96
+ # Log an debut message.
97
+ #
98
+ # @param [String] msg The message to log.
99
+ # @param [Proc] &block Optional context block.
100
+ #
101
+ def debug(msg, &block)
102
+ log_message(:debug, msg, &block)
103
+ end
104
+
105
+ #
106
+ # Delegate all methods to the underlying logger.
107
+ #
108
+ # @param [String, Symbol] name The method to delegate.
109
+ # @param [Array<any>] *args The list of method arguments.
110
+ # @param [Proc] &block Block passed to the method.
111
+ #
112
+ # @return [Any] The method return value
113
+ #
114
+ def method_missing(name, *args, &block)
115
+ if logger.respond_to?(name)
116
+ logger.send(name, *args, &block)
117
+ else
118
+ super
119
+ end
120
+ end
121
+
122
+ #
123
+ # Check if the class respond to a certain method.
124
+ #
125
+ # @param [String, Symbol] name The name of the method.
126
+ # @param [Boolean] include_private Whether to check private methods or not. Default to false.
127
+ #
128
+ # @return [Boolean] Return true if the class respond to this method.
129
+ #
130
+ def respond_to_missing?(name, include_private = false)
131
+ logger.respond_to?(name) || super
132
+ end
133
+
134
+ private
135
+
136
+ #
137
+ # Log a message for the provided log level.
138
+ #
139
+ # @param [String, Symbol] level The log level
140
+ # @param [String] msg The message to log.
141
+ # @param [Proc] &block Optional context block.
142
+ #
143
+ def log_message(level, msg, &block)
144
+ payload_block = block || log_block
145
+
146
+ # ActiveSupport::Logger does not support passing a payload through a block on top
147
+ # of a message.
148
+ if defined?(ActiveSupport::Logger) && logger.is_a?(ActiveSupport::Logger)
149
+ logger.send(level) { "#{formatted_message(msg)} -- #{payload_block.call}" }
150
+ else
151
+ logger.send(level, formatted_message(msg), &payload_block)
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cloudtasker/backend/google_cloud_task'
4
+
5
+ namespace :cloudtasker do
6
+ desc 'Setup the Cloud Task queue'
7
+ task setup_queue: :environment do
8
+ Cloudtasker::Backend::GoogleCloudTask.setup_queue
9
+ end
10
+ 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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-18 00:00:00.000000000 Z
11
+ date: 2019-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: appraisal
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -220,10 +234,11 @@ dependencies:
220
234
  - - ">="
221
235
  - !ruby/object:Gem::Version
222
236
  version: '0'
223
- description: Manage GCP Cloud Tasks in your app. (under development)
237
+ description: Manage GCP Cloud Tasks in your app. (alpha)
224
238
  email:
225
239
  - arnaud.lachaume@keypup.io
226
- executables: []
240
+ executables:
241
+ - cloudtasker
227
242
  extensions: []
228
243
  extra_rdoc_files: []
229
244
  files:
@@ -231,6 +246,7 @@ files:
231
246
  - ".rspec"
232
247
  - ".rubocop.yml"
233
248
  - ".travis.yml"
249
+ - Appraisals
234
250
  - CODE_OF_CONDUCT.md
235
251
  - Gemfile
236
252
  - Gemfile.lock
@@ -243,27 +259,57 @@ files:
243
259
  - bin/setup
244
260
  - cloudtasker.gemspec
245
261
  - config/routes.rb
262
+ - docs/BATCH_JOBS.md
263
+ - docs/CRON_JOBS.md
264
+ - docs/UNIQUE_JOBS.md
265
+ - exe/cloudtasker
266
+ - gemfiles/.bundle/config
267
+ - gemfiles/google_cloud_tasks_1.0.gemfile
268
+ - gemfiles/google_cloud_tasks_1.0.gemfile.lock
269
+ - gemfiles/google_cloud_tasks_1.1.gemfile
270
+ - gemfiles/google_cloud_tasks_1.1.gemfile.lock
271
+ - gemfiles/google_cloud_tasks_1.2.gemfile
272
+ - gemfiles/google_cloud_tasks_1.2.gemfile.lock
273
+ - gemfiles/google_cloud_tasks_1.3.gemfile
274
+ - gemfiles/google_cloud_tasks_1.3.gemfile.lock
275
+ - gemfiles/rails_4.0.gemfile
276
+ - gemfiles/rails_4.1.gemfile
277
+ - gemfiles/rails_4.2.gemfile
278
+ - gemfiles/rails_5.0.gemfile
279
+ - gemfiles/rails_5.1.gemfile
280
+ - gemfiles/rails_5.2.gemfile
281
+ - gemfiles/rails_5.2.gemfile.lock
282
+ - gemfiles/rails_6.0.gemfile
283
+ - gemfiles/rails_6.0.gemfile.lock
246
284
  - lib/cloudtasker.rb
247
285
  - lib/cloudtasker/authentication_error.rb
248
286
  - lib/cloudtasker/authenticator.rb
287
+ - lib/cloudtasker/backend/google_cloud_task.rb
288
+ - lib/cloudtasker/backend/memory_task.rb
289
+ - lib/cloudtasker/backend/redis_task.rb
249
290
  - lib/cloudtasker/batch.rb
250
291
  - lib/cloudtasker/batch/batch_progress.rb
251
292
  - lib/cloudtasker/batch/extension/worker.rb
252
293
  - lib/cloudtasker/batch/job.rb
253
294
  - lib/cloudtasker/batch/middleware.rb
254
295
  - lib/cloudtasker/batch/middleware/server.rb
296
+ - lib/cloudtasker/cli.rb
297
+ - lib/cloudtasker/cloud_task.rb
255
298
  - lib/cloudtasker/config.rb
256
299
  - lib/cloudtasker/cron.rb
257
300
  - lib/cloudtasker/cron/job.rb
258
301
  - lib/cloudtasker/cron/middleware.rb
259
302
  - lib/cloudtasker/cron/middleware/server.rb
260
303
  - lib/cloudtasker/cron/schedule.rb
304
+ - lib/cloudtasker/dead_worker_error.rb
261
305
  - lib/cloudtasker/engine.rb
262
306
  - lib/cloudtasker/invalid_worker_error.rb
307
+ - lib/cloudtasker/local_server.rb
263
308
  - lib/cloudtasker/meta_store.rb
264
309
  - lib/cloudtasker/middleware/chain.rb
310
+ - lib/cloudtasker/railtie.rb
265
311
  - lib/cloudtasker/redis_client.rb
266
- - lib/cloudtasker/task.rb
312
+ - lib/cloudtasker/testing.rb
267
313
  - lib/cloudtasker/unique_job.rb
268
314
  - lib/cloudtasker/unique_job/conflict_strategy/base_strategy.rb
269
315
  - lib/cloudtasker/unique_job/conflict_strategy/raise.rb
@@ -281,6 +327,9 @@ files:
281
327
  - lib/cloudtasker/unique_job/middleware/server.rb
282
328
  - lib/cloudtasker/version.rb
283
329
  - lib/cloudtasker/worker.rb
330
+ - lib/cloudtasker/worker_handler.rb
331
+ - lib/cloudtasker/worker_logger.rb
332
+ - lib/tasks/setup_queue.rake
284
333
  homepage: https://github.com/keypup-io/cloudtasker
285
334
  licenses:
286
335
  - MIT
@@ -307,5 +356,5 @@ rubyforge_project:
307
356
  rubygems_version: 2.7.9
308
357
  signing_key:
309
358
  specification_version: 4
310
- summary: Manage GCP Cloud Tasks in your app. (under development)
359
+ summary: Manage GCP Cloud Tasks in your app. (alpha)
311
360
  test_files: []