cloudtasker 0.6.0 → 0.9.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +5 -0
  4. data/.travis.yml +3 -3
  5. data/CHANGELOG.md +38 -0
  6. data/README.md +142 -26
  7. data/_config.yml +1 -0
  8. data/app/controllers/cloudtasker/worker_controller.rb +21 -5
  9. data/cloudtasker.gemspec +2 -2
  10. data/docs/BATCH_JOBS.md +29 -4
  11. data/docs/CRON_JOBS.md +18 -14
  12. data/exe/cloudtasker +13 -1
  13. data/gemfiles/google_cloud_tasks_1.0.gemfile.lock +26 -9
  14. data/gemfiles/google_cloud_tasks_1.1.gemfile.lock +26 -9
  15. data/gemfiles/google_cloud_tasks_1.2.gemfile.lock +27 -10
  16. data/gemfiles/google_cloud_tasks_1.3.gemfile.lock +26 -9
  17. data/gemfiles/rails_5.2.gemfile.lock +26 -9
  18. data/gemfiles/rails_6.0.gemfile.lock +27 -10
  19. data/lib/cloudtasker.rb +0 -1
  20. data/lib/cloudtasker/backend/google_cloud_task.rb +65 -12
  21. data/lib/cloudtasker/backend/memory_task.rb +5 -3
  22. data/lib/cloudtasker/backend/redis_task.rb +24 -13
  23. data/lib/cloudtasker/batch/batch_progress.rb +11 -2
  24. data/lib/cloudtasker/batch/job.rb +18 -4
  25. data/lib/cloudtasker/cli.rb +6 -5
  26. data/lib/cloudtasker/cloud_task.rb +4 -2
  27. data/lib/cloudtasker/config.rb +30 -9
  28. data/lib/cloudtasker/cron/job.rb +2 -2
  29. data/lib/cloudtasker/cron/schedule.rb +26 -14
  30. data/lib/cloudtasker/local_server.rb +44 -22
  31. data/lib/cloudtasker/redis_client.rb +10 -7
  32. data/lib/cloudtasker/unique_job/job.rb +2 -2
  33. data/lib/cloudtasker/version.rb +1 -1
  34. data/lib/cloudtasker/worker.rb +46 -10
  35. data/lib/cloudtasker/worker_handler.rb +7 -5
  36. data/lib/cloudtasker/worker_logger.rb +1 -1
  37. data/lib/cloudtasker/worker_wrapper.rb +52 -0
  38. data/lib/tasks/setup_queue.rake +12 -2
  39. metadata +6 -6
  40. data/Gemfile.lock +0 -280
  41. data/lib/cloudtasker/railtie.rb +0 -10
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- cloudtasker (0.2.0)
4
+ cloudtasker (0.9.0)
5
5
  activesupport
6
6
  fugit
7
7
  google-cloud-tasks
@@ -82,11 +82,21 @@ GEM
82
82
  erubi (1.9.0)
83
83
  et-orbi (1.2.2)
84
84
  tzinfo
85
- faraday (0.17.0)
85
+ faraday (0.17.1)
86
86
  multipart-post (>= 1.2, < 3)
87
+ faraday-http-cache (2.0.0)
88
+ faraday (~> 0.8)
87
89
  fugit (1.3.3)
88
90
  et-orbi (~> 1.1, >= 1.1.8)
89
91
  raabro (~> 1.1)
92
+ github_changelog_generator (1.15.0)
93
+ activesupport
94
+ faraday-http-cache
95
+ multi_json
96
+ octokit (~> 4.6)
97
+ rainbow (>= 2.2.1)
98
+ rake (>= 10.0)
99
+ retriable (~> 3.0)
90
100
  globalid (0.4.2)
91
101
  activesupport (>= 4.2.0)
92
102
  google-cloud-tasks (1.3.0)
@@ -100,7 +110,7 @@ GEM
100
110
  googleauth (~> 0.9)
101
111
  grpc (~> 1.24)
102
112
  rly (~> 0.2.3)
103
- google-protobuf (3.10.1)
113
+ google-protobuf (3.11.1)
104
114
  googleapis-common-protos (1.3.9)
105
115
  google-protobuf (~> 3.0)
106
116
  googleapis-common-protos-types (~> 1.0)
@@ -125,14 +135,14 @@ GEM
125
135
  concurrent-ruby (~> 1.0)
126
136
  jaro_winkler (1.5.4)
127
137
  jwt (2.2.1)
128
- loofah (2.3.1)
138
+ loofah (2.4.0)
129
139
  crass (~> 1.0.2)
130
140
  nokogiri (>= 1.5.9)
131
141
  mail (2.7.1)
132
142
  mini_mime (>= 0.1.1)
133
143
  marcel (0.3.3)
134
144
  mimemagic (~> 0.3.2)
135
- memoist (0.16.1)
145
+ memoist (0.16.2)
136
146
  method_source (0.9.2)
137
147
  mimemagic (0.3.3)
138
148
  mini_mime (1.0.2)
@@ -141,10 +151,12 @@ GEM
141
151
  multi_json (1.14.1)
142
152
  multipart-post (2.1.1)
143
153
  nio4r (2.5.2)
144
- nokogiri (1.10.5)
154
+ nokogiri (1.10.7)
145
155
  mini_portile2 (~> 2.4.0)
156
+ octokit (4.14.0)
157
+ sawyer (~> 0.8.0, >= 0.5.3)
146
158
  os (1.0.1)
147
- parallel (1.19.0)
159
+ parallel (1.19.1)
148
160
  parser (2.6.5.0)
149
161
  ast (~> 2.4.0)
150
162
  public_suffix (4.0.1)
@@ -181,6 +193,7 @@ GEM
181
193
  rainbow (3.0.0)
182
194
  rake (10.5.0)
183
195
  redis (4.1.3)
196
+ retriable (3.1.2)
184
197
  rly (0.2.3)
185
198
  rspec (3.9.0)
186
199
  rspec-core (~> 3.9.0)
@@ -210,10 +223,13 @@ GEM
210
223
  rainbow (>= 2.2.2, < 4.0)
211
224
  ruby-progressbar (~> 1.7)
212
225
  unicode-display_width (>= 1.4.0, < 1.7)
213
- rubocop-rspec (1.36.0)
226
+ rubocop-rspec (1.37.0)
214
227
  rubocop (>= 0.68.1)
215
228
  ruby-progressbar (1.10.1)
216
229
  safe_yaml (1.0.5)
230
+ sawyer (0.8.2)
231
+ addressable (>= 2.3.5)
232
+ faraday (> 0.8, < 2.0)
217
233
  signet (0.12.0)
218
234
  addressable (~> 2.3)
219
235
  faraday (~> 0.9)
@@ -240,7 +256,7 @@ GEM
240
256
  websocket-driver (0.7.1)
241
257
  websocket-extensions (>= 0.1.0)
242
258
  websocket-extensions (0.1.4)
243
- zeitwerk (2.2.1)
259
+ zeitwerk (2.2.2)
244
260
 
245
261
  PLATFORMS
246
262
  ruby
@@ -249,6 +265,7 @@ DEPENDENCIES
249
265
  appraisal
250
266
  bundler (~> 2.0)
251
267
  cloudtasker!
268
+ github_changelog_generator
252
269
  google-cloud-tasks (= 1.3)
253
270
  rails
254
271
  rake (~> 10.0)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- cloudtasker (0.2.0)
4
+ cloudtasker (0.9.0)
5
5
  activesupport
6
6
  fugit
7
7
  google-cloud-tasks
@@ -69,11 +69,21 @@ GEM
69
69
  erubi (1.9.0)
70
70
  et-orbi (1.2.2)
71
71
  tzinfo
72
- faraday (0.17.0)
72
+ faraday (0.17.1)
73
73
  multipart-post (>= 1.2, < 3)
74
+ faraday-http-cache (2.0.0)
75
+ faraday (~> 0.8)
74
76
  fugit (1.3.3)
75
77
  et-orbi (~> 1.1, >= 1.1.8)
76
78
  raabro (~> 1.1)
79
+ github_changelog_generator (1.15.0)
80
+ activesupport
81
+ faraday-http-cache
82
+ multi_json
83
+ octokit (~> 4.6)
84
+ rainbow (>= 2.2.1)
85
+ rake (>= 10.0)
86
+ retriable (~> 3.0)
77
87
  globalid (0.4.2)
78
88
  activesupport (>= 4.2.0)
79
89
  google-cloud-tasks (1.3.1)
@@ -87,7 +97,7 @@ GEM
87
97
  googleauth (~> 0.9)
88
98
  grpc (~> 1.24)
89
99
  rly (~> 0.2.3)
90
- google-protobuf (3.10.1)
100
+ google-protobuf (3.11.2-universal-darwin)
91
101
  googleapis-common-protos (1.3.9)
92
102
  google-protobuf (~> 3.0)
93
103
  googleapis-common-protos-types (~> 1.0)
@@ -101,7 +111,7 @@ GEM
101
111
  multi_json (~> 1.11)
102
112
  os (>= 0.9, < 2.0)
103
113
  signet (~> 0.12)
104
- grpc (1.25.0)
114
+ grpc (1.26.0-universal-darwin)
105
115
  google-protobuf (~> 3.8)
106
116
  googleapis-common-protos-types (~> 1.0)
107
117
  grpc-google-iam-v1 (0.6.9)
@@ -112,14 +122,14 @@ GEM
112
122
  concurrent-ruby (~> 1.0)
113
123
  jaro_winkler (1.5.4)
114
124
  jwt (2.2.1)
115
- loofah (2.3.1)
125
+ loofah (2.4.0)
116
126
  crass (~> 1.0.2)
117
127
  nokogiri (>= 1.5.9)
118
128
  mail (2.7.1)
119
129
  mini_mime (>= 0.1.1)
120
130
  marcel (0.3.3)
121
131
  mimemagic (~> 0.3.2)
122
- memoist (0.16.1)
132
+ memoist (0.16.2)
123
133
  method_source (0.9.2)
124
134
  mimemagic (0.3.3)
125
135
  mini_mime (1.0.2)
@@ -128,10 +138,12 @@ GEM
128
138
  multi_json (1.14.1)
129
139
  multipart-post (2.1.1)
130
140
  nio4r (2.5.2)
131
- nokogiri (1.10.5)
141
+ nokogiri (1.10.7)
132
142
  mini_portile2 (~> 2.4.0)
143
+ octokit (4.14.0)
144
+ sawyer (~> 0.8.0, >= 0.5.3)
133
145
  os (1.0.1)
134
- parallel (1.19.0)
146
+ parallel (1.19.1)
135
147
  parser (2.6.5.0)
136
148
  ast (~> 2.4.0)
137
149
  public_suffix (4.0.1)
@@ -166,6 +178,7 @@ GEM
166
178
  rainbow (3.0.0)
167
179
  rake (10.5.0)
168
180
  redis (4.1.3)
181
+ retriable (3.1.2)
169
182
  rly (0.2.3)
170
183
  rspec (3.9.0)
171
184
  rspec-core (~> 3.9.0)
@@ -195,10 +208,13 @@ GEM
195
208
  rainbow (>= 2.2.2, < 4.0)
196
209
  ruby-progressbar (~> 1.7)
197
210
  unicode-display_width (>= 1.4.0, < 1.7)
198
- rubocop-rspec (1.36.0)
211
+ rubocop-rspec (1.37.0)
199
212
  rubocop (>= 0.68.1)
200
213
  ruby-progressbar (1.10.1)
201
214
  safe_yaml (1.0.5)
215
+ sawyer (0.8.2)
216
+ addressable (>= 2.3.5)
217
+ faraday (> 0.8, < 2.0)
202
218
  signet (0.12.0)
203
219
  addressable (~> 2.3)
204
220
  faraday (~> 0.9)
@@ -233,6 +249,7 @@ DEPENDENCIES
233
249
  appraisal
234
250
  bundler (~> 2.0)
235
251
  cloudtasker!
252
+ github_changelog_generator
236
253
  rails (= 5.2)
237
254
  rake (~> 10.0)
238
255
  rspec (~> 3.0)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- cloudtasker (0.2.0)
4
+ cloudtasker (0.9.0)
5
5
  activesupport
6
6
  fugit
7
7
  google-cloud-tasks
@@ -82,11 +82,21 @@ GEM
82
82
  erubi (1.9.0)
83
83
  et-orbi (1.2.2)
84
84
  tzinfo
85
- faraday (0.17.0)
85
+ faraday (0.17.1)
86
86
  multipart-post (>= 1.2, < 3)
87
+ faraday-http-cache (2.0.0)
88
+ faraday (~> 0.8)
87
89
  fugit (1.3.3)
88
90
  et-orbi (~> 1.1, >= 1.1.8)
89
91
  raabro (~> 1.1)
92
+ github_changelog_generator (1.15.0)
93
+ activesupport
94
+ faraday-http-cache
95
+ multi_json
96
+ octokit (~> 4.6)
97
+ rainbow (>= 2.2.1)
98
+ rake (>= 10.0)
99
+ retriable (~> 3.0)
90
100
  globalid (0.4.2)
91
101
  activesupport (>= 4.2.0)
92
102
  google-cloud-tasks (1.3.1)
@@ -100,7 +110,7 @@ GEM
100
110
  googleauth (~> 0.9)
101
111
  grpc (~> 1.24)
102
112
  rly (~> 0.2.3)
103
- google-protobuf (3.10.1-universal-darwin)
113
+ google-protobuf (3.11.2-universal-darwin)
104
114
  googleapis-common-protos (1.3.9)
105
115
  google-protobuf (~> 3.0)
106
116
  googleapis-common-protos-types (~> 1.0)
@@ -114,7 +124,7 @@ GEM
114
124
  multi_json (~> 1.11)
115
125
  os (>= 0.9, < 2.0)
116
126
  signet (~> 0.12)
117
- grpc (1.25.0-universal-darwin)
127
+ grpc (1.26.0-universal-darwin)
118
128
  google-protobuf (~> 3.8)
119
129
  googleapis-common-protos-types (~> 1.0)
120
130
  grpc-google-iam-v1 (0.6.9)
@@ -125,14 +135,14 @@ GEM
125
135
  concurrent-ruby (~> 1.0)
126
136
  jaro_winkler (1.5.4)
127
137
  jwt (2.2.1)
128
- loofah (2.3.1)
138
+ loofah (2.4.0)
129
139
  crass (~> 1.0.2)
130
140
  nokogiri (>= 1.5.9)
131
141
  mail (2.7.1)
132
142
  mini_mime (>= 0.1.1)
133
143
  marcel (0.3.3)
134
144
  mimemagic (~> 0.3.2)
135
- memoist (0.16.1)
145
+ memoist (0.16.2)
136
146
  method_source (0.9.2)
137
147
  mimemagic (0.3.3)
138
148
  mini_mime (1.0.2)
@@ -141,10 +151,12 @@ GEM
141
151
  multi_json (1.14.1)
142
152
  multipart-post (2.1.1)
143
153
  nio4r (2.5.2)
144
- nokogiri (1.10.5)
154
+ nokogiri (1.10.7)
145
155
  mini_portile2 (~> 2.4.0)
156
+ octokit (4.14.0)
157
+ sawyer (~> 0.8.0, >= 0.5.3)
146
158
  os (1.0.1)
147
- parallel (1.19.0)
159
+ parallel (1.19.1)
148
160
  parser (2.6.5.0)
149
161
  ast (~> 2.4.0)
150
162
  public_suffix (4.0.1)
@@ -181,6 +193,7 @@ GEM
181
193
  rainbow (3.0.0)
182
194
  rake (10.5.0)
183
195
  redis (4.1.3)
196
+ retriable (3.1.2)
184
197
  rly (0.2.3)
185
198
  rspec (3.9.0)
186
199
  rspec-core (~> 3.9.0)
@@ -210,10 +223,13 @@ GEM
210
223
  rainbow (>= 2.2.2, < 4.0)
211
224
  ruby-progressbar (~> 1.7)
212
225
  unicode-display_width (>= 1.4.0, < 1.7)
213
- rubocop-rspec (1.36.0)
226
+ rubocop-rspec (1.37.0)
214
227
  rubocop (>= 0.68.1)
215
228
  ruby-progressbar (1.10.1)
216
229
  safe_yaml (1.0.5)
230
+ sawyer (0.8.2)
231
+ addressable (>= 2.3.5)
232
+ faraday (> 0.8, < 2.0)
217
233
  signet (0.12.0)
218
234
  addressable (~> 2.3)
219
235
  faraday (~> 0.9)
@@ -240,7 +256,7 @@ GEM
240
256
  websocket-driver (0.7.1)
241
257
  websocket-extensions (>= 0.1.0)
242
258
  websocket-extensions (0.1.4)
243
- zeitwerk (2.2.1)
259
+ zeitwerk (2.2.2)
244
260
 
245
261
  PLATFORMS
246
262
  ruby
@@ -249,6 +265,7 @@ DEPENDENCIES
249
265
  appraisal
250
266
  bundler (~> 2.0)
251
267
  cloudtasker!
268
+ github_changelog_generator
252
269
  rails (= 6.0)
253
270
  rake (~> 10.0)
254
271
  rspec (~> 3.0)
data/lib/cloudtasker.rb CHANGED
@@ -47,5 +47,4 @@ module Cloudtasker
47
47
  end
48
48
  end
49
49
 
50
- require 'cloudtasker/railtie' if defined?(Rails)
51
50
  require 'cloudtasker/engine' if defined?(::Rails::Engine)
@@ -9,15 +9,28 @@ module Cloudtasker
9
9
  #
10
10
  # Create the queue configured in Cloudtasker if it does not already exist.
11
11
  #
12
+ # @param [String] queue_name The relative name of the queue.
13
+ #
12
14
  # @return [Google::Cloud::Tasks::V2beta3::Queue] The queue
13
15
  #
14
- def self.setup_queue
15
- client.get_queue(queue_path)
16
+ def self.setup_queue(**opts)
17
+ # Build full queue path
18
+ queue_name = opts[:name] || Cloudtasker::Config::DEFAULT_JOB_QUEUE
19
+ full_queue_name = queue_path(queue_name)
20
+
21
+ # Try to get existing queue
22
+ client.get_queue(full_queue_name)
16
23
  rescue Google::Gax::RetryError
24
+ # Extract options
25
+ concurrency = (opts[:concurrency] || Cloudtasker::Config::DEFAULT_QUEUE_CONCURRENCY).to_i
26
+ retries = (opts[:retries] || Cloudtasker::Config::DEFAULT_QUEUE_RETRIES).to_i
27
+
28
+ # Create queue on 'not found' error
17
29
  client.create_queue(
18
30
  client.location_path(config.gcp_project_id, config.gcp_location_id),
19
- name: queue_path,
20
- retry_config: { max_attempts: -1 }
31
+ name: full_queue_name,
32
+ retry_config: { max_attempts: retries },
33
+ rate_limits: { max_concurrent_dispatches: concurrency }
21
34
  )
22
35
  end
23
36
 
@@ -42,13 +55,15 @@ module Cloudtasker
42
55
  #
43
56
  # Return the fully qualified path for the Cloud Task queue.
44
57
  #
58
+ # @param [String] queue_name The relative name of the queue.
59
+ #
45
60
  # @return [String] The queue path.
46
61
  #
47
- def self.queue_path
62
+ def self.queue_path(queue_name)
48
63
  client.queue_path(
49
64
  config.gcp_project_id,
50
65
  config.gcp_location_id,
51
- config.gcp_queue_id
66
+ [config.gcp_queue_prefix, queue_name].join('-')
52
67
  )
53
68
  end
54
69
 
@@ -67,6 +82,29 @@ module Cloudtasker
67
82
  Google::Protobuf::Timestamp.new.tap { |e| e.seconds = schedule_time.to_i }
68
83
  end
69
84
 
85
+ #
86
+ # Format the job payload sent to Cloud Tasks.
87
+ #
88
+ # @param [Hash] hash The worker payload.
89
+ #
90
+ # @return [Hash] The Cloud Task payloadd.
91
+ #
92
+ def self.format_task_payload(payload)
93
+ payload = JSON.parse(payload.to_json, symbolize_names: true) # deep dup
94
+
95
+ # Format schedule time to Google Protobuf timestamp
96
+ payload[:schedule_time] = format_schedule_time(payload[:schedule_time])
97
+
98
+ # Encode job content to support UTF-8. Google Cloud Task
99
+ # expect content to be ASCII-8BIT compatible (binary)
100
+ payload[:http_request][:headers] ||= {}
101
+ payload[:http_request][:headers][Cloudtasker::Config::CONTENT_TYPE_HEADER] = 'text/json'
102
+ payload[:http_request][:headers][Cloudtasker::Config::ENCODING_HEADER] = 'Base64'
103
+ payload[:http_request][:body] = Base64.encode64(payload[:http_request][:body])
104
+
105
+ payload
106
+ end
107
+
70
108
  #
71
109
  # Find a task by id.
72
110
  #
@@ -89,13 +127,13 @@ module Cloudtasker
89
127
  # @return [Cloudtasker::Backend::GoogleCloudTask, nil] The created task.
90
128
  #
91
129
  def self.create(payload)
92
- # Format payload
93
- payload = payload.merge(
94
- schedule_time: format_schedule_time(payload[:schedule_time])
95
- ).compact
130
+ payload = format_task_payload(payload)
131
+
132
+ # Extract relative queue name
133
+ relative_queue = payload.delete(:queue)
96
134
 
97
135
  # Create task
98
- resp = client.create_task(queue_path, payload)
136
+ resp = client.create_task(queue_path(relative_queue), payload)
99
137
  resp ? new(resp) : nil
100
138
  rescue Google::Gax::RetryError
101
139
  nil
@@ -121,6 +159,20 @@ module Cloudtasker
121
159
  @gcp_task = gcp_task
122
160
  end
123
161
 
162
+ #
163
+ # Return the relative queue (queue name minus prefix) the task is in.
164
+ #
165
+ # @return [String] The relative queue name
166
+ #
167
+ def relative_queue
168
+ gcp_task
169
+ .name
170
+ .match(%r{/queues/([^/]+)})
171
+ &.captures
172
+ &.first
173
+ &.sub("#{self.class.config.gcp_queue_prefix}-", '')
174
+ end
175
+
124
176
  #
125
177
  # Return a hash description of the task.
126
178
  #
@@ -131,7 +183,8 @@ module Cloudtasker
131
183
  id: gcp_task.name,
132
184
  http_request: gcp_task.to_h[:http_request],
133
185
  schedule_time: gcp_task.to_h.dig(:schedule_time, :seconds).to_i,
134
- retries: gcp_task.to_h[:response_count]
186
+ retries: gcp_task.to_h[:response_count],
187
+ queue: relative_queue
135
188
  }
136
189
  end
137
190
  end