google-cloud-pubsub 1.7.1 → 2.1.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +2 -1
  3. data/CHANGELOG.md +53 -0
  4. data/OVERVIEW.md +26 -58
  5. data/lib/google-cloud-pubsub.rb +14 -13
  6. data/lib/google/cloud/pubsub.rb +15 -18
  7. data/lib/google/cloud/pubsub/async_publisher.rb +2 -3
  8. data/lib/google/cloud/pubsub/credentials.rb +2 -2
  9. data/lib/google/cloud/pubsub/message.rb +1 -1
  10. data/lib/google/cloud/pubsub/project.rb +1 -1
  11. data/lib/google/cloud/pubsub/received_message.rb +4 -4
  12. data/lib/google/cloud/pubsub/service.rb +110 -260
  13. data/lib/google/cloud/pubsub/subscriber.rb +3 -3
  14. data/lib/google/cloud/pubsub/subscriber/stream.rb +3 -2
  15. data/lib/google/cloud/pubsub/subscription.rb +86 -11
  16. data/lib/google/cloud/pubsub/subscription/push_config.rb +55 -31
  17. data/lib/google/cloud/pubsub/topic.rb +52 -14
  18. data/lib/google/cloud/pubsub/version.rb +1 -1
  19. metadata +8 -79
  20. data/lib/google/cloud/pubsub/v1.rb +0 -17
  21. data/lib/google/cloud/pubsub/v1/credentials.rb +0 -41
  22. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/iam_policy.rb +0 -21
  23. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/options.rb +0 -21
  24. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/policy.rb +0 -21
  25. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +0 -91
  26. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/empty.rb +0 -29
  27. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +0 -222
  28. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +0 -113
  29. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +0 -807
  30. data/lib/google/cloud/pubsub/v1/doc/google/type/expr.rb +0 -19
  31. data/lib/google/cloud/pubsub/v1/publisher_client.rb +0 -928
  32. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +0 -120
  33. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +0 -1463
  34. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +0 -153
  35. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -266
  36. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -215
@@ -18,17 +18,15 @@ require "google/cloud/pubsub/credentials"
18
18
  require "google/cloud/pubsub/convert"
19
19
  require "google/cloud/pubsub/version"
20
20
  require "google/cloud/pubsub/v1"
21
- require "google/gax/errors"
22
21
  require "securerandom"
23
22
 
24
23
  module Google
25
24
  module Cloud
26
25
  module PubSub
27
26
  ##
28
- # @private Represents the GAX Pub/Sub service, including all the API
29
- # methods.
27
+ # @private Represents the Pub/Sub service API, including IAM mixins.
30
28
  class Service
31
- attr_accessor :project, :credentials, :host, :timeout, :client_config
29
+ attr_accessor :project, :credentials, :host, :timeout
32
30
  ###
33
31
  # The same client_id is used across all streaming pull connections that are created by this client. This is
34
32
  # intentional, as it indicates to the server that any guarantees, such as message ordering, made for a stream
@@ -38,44 +36,25 @@ module Google
38
36
 
39
37
  ##
40
38
  # Creates a new Service instance.
41
- def initialize project, credentials, host: nil, timeout: nil,
42
- client_config: nil
39
+ def initialize project, credentials, host: nil, timeout: nil
43
40
  @project = project
44
41
  @credentials = credentials
45
- @host = host || V1::PublisherClient::SERVICE_ADDRESS
42
+ @host = host
46
43
  @timeout = timeout
47
- @client_config = client_config || {}
48
44
  @client_id = SecureRandom.uuid.freeze
49
45
  end
50
46
 
51
- def channel
52
- require "grpc"
53
- GRPC::Core::Channel.new host, chan_args, chan_creds
54
- end
55
-
56
- def chan_args
57
- { "grpc.max_send_message_length" => -1,
58
- "grpc.max_receive_message_length" => -1,
59
- "grpc.keepalive_time_ms" => 300_000,
60
- "grpc.service_config_disable_resolution" => 1 }
61
- end
62
-
63
- def chan_creds
64
- return credentials if insecure?
65
- require "grpc"
66
- GRPC::Core::ChannelCredentials.new.compose GRPC::Core::CallCredentials.new credentials.client.updater_proc
67
- end
68
-
69
47
  def subscriber
70
48
  return mocked_subscriber if mocked_subscriber
71
49
  @subscriber ||= begin
72
- V1::SubscriberClient.new(
73
- credentials: channel,
74
- timeout: timeout,
75
- client_config: client_config,
76
- lib_name: "gccl",
77
- lib_version: Google::Cloud::PubSub::VERSION
78
- )
50
+ V1::Subscriber::Client.new do |config|
51
+ config.credentials = credentials if credentials
52
+ config.timeout = timeout if timeout
53
+ config.endpoint = host if host
54
+ config.lib_name = "gccl"
55
+ config.lib_version = Google::Cloud::PubSub::VERSION
56
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
57
+ end
79
58
  end
80
59
  end
81
60
  attr_accessor :mocked_subscriber
@@ -83,20 +62,32 @@ module Google
83
62
  def publisher
84
63
  return mocked_publisher if mocked_publisher
85
64
  @publisher ||= begin
86
- V1::PublisherClient.new(
87
- credentials: channel,
88
- timeout: timeout,
89
- client_config: client_config,
90
- lib_name: "gccl",
91
- lib_version: Google::Cloud::PubSub::VERSION
92
- )
65
+ V1::Publisher::Client.new do |config|
66
+ config.credentials = credentials if credentials
67
+ config.timeout = timeout if timeout
68
+ config.endpoint = host if host
69
+ config.lib_name = "gccl"
70
+ config.lib_version = Google::Cloud::PubSub::VERSION
71
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
72
+ end
93
73
  end
94
74
  end
95
75
  attr_accessor :mocked_publisher
96
76
 
97
- def insecure?
98
- credentials == :this_channel_is_insecure
77
+ def iam
78
+ return mocked_iam if mocked_iam
79
+ @iam ||= begin
80
+ V1::IAMPolicy::Client.new do |config|
81
+ config.credentials = credentials if credentials
82
+ config.timeout = timeout if timeout
83
+ config.endpoint = host if host
84
+ config.lib_name = "gccl"
85
+ config.lib_version = Google::Cloud::PubSub::VERSION
86
+ config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
87
+ end
88
+ end
99
89
  end
90
+ attr_accessor :mocked_iam
100
91
 
101
92
  ##
102
93
  # Gets the configuration of a topic.
@@ -105,30 +96,17 @@ module Google
105
96
  # If other attributes are added in the future,
106
97
  # they will be returned here.
107
98
  def get_topic topic_name, options = {}
108
- execute do
109
- publisher.get_topic topic_path(topic_name, options),
110
- options: default_options
111
- end
99
+ publisher.get_topic topic: topic_path(topic_name, options)
112
100
  end
113
101
 
114
102
  ##
115
103
  # Lists matching topics.
116
104
  def list_topics options = {}
117
- call_options = default_options
118
- if (token = options[:token])
119
- call_options = Google::Gax::CallOptions.new(
120
- kwargs: default_headers,
121
- page_token: token
122
- )
123
- end
105
+ paged_enum = publisher.list_topics project: project_path(options),
106
+ page_size: options[:max],
107
+ page_token: options[:token]
124
108
 
125
- execute do
126
- paged_enum = publisher.list_topics project_path(options),
127
- page_size: options[:max],
128
- options: call_options
129
-
130
- paged_enum.page.response
131
- end
109
+ paged_enum.response
132
110
  end
133
111
 
134
112
  ##
@@ -140,21 +118,16 @@ module Google
140
118
  }
141
119
  end
142
120
 
143
- execute do
144
- publisher.create_topic \
145
- topic_path(topic_name, options),
146
- labels: labels,
147
- kms_key_name: kms_key_name,
148
- message_storage_policy: message_storage_policy,
149
- options: default_options
150
- end
121
+ publisher.create_topic \
122
+ name: topic_path(topic_name, options),
123
+ labels: labels,
124
+ kms_key_name: kms_key_name,
125
+ message_storage_policy: message_storage_policy
151
126
  end
152
127
 
153
128
  def update_topic topic_obj, *fields
154
129
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
155
- execute do
156
- publisher.update_topic topic_obj, mask, options: default_options
157
- end
130
+ publisher.update_topic topic: topic_obj, update_mask: mask
158
131
  end
159
132
 
160
133
  ##
@@ -163,10 +136,7 @@ module Google
163
136
  # exist. After a topic is deleted, a new topic may be created with the
164
137
  # same name.
165
138
  def delete_topic topic_name
166
- execute do
167
- publisher.delete_topic topic_path(topic_name),
168
- options: default_options
169
- end
139
+ publisher.delete_topic topic: topic_path(topic_name)
170
140
  end
171
141
 
172
142
  ##
@@ -175,143 +145,93 @@ module Google
175
145
  # The messages parameter is an array of arrays.
176
146
  # The first element is the data, second is attributes hash.
177
147
  def publish topic, messages
178
- execute do
179
- publisher.publish topic_path(topic), messages,
180
- options: default_options
181
- end
148
+ publisher.publish topic: topic_path(topic), messages: messages
182
149
  end
183
150
 
184
151
  ##
185
152
  # Gets the details of a subscription.
186
153
  def get_subscription subscription_name, options = {}
187
- subscription = subscription_path subscription_name, options
188
- execute do
189
- subscriber.get_subscription subscription, options: default_options
190
- end
154
+ subscriber.get_subscription subscription: subscription_path(subscription_name, options)
191
155
  end
192
156
 
193
157
  ##
194
158
  # Lists matching subscriptions by project and topic.
195
159
  def list_topics_subscriptions topic, options = {}
196
- call_options = default_options
197
- if (token = options[:token])
198
- call_options = Google::Gax::CallOptions.new(
199
- kwargs: default_headers,
200
- page_token: token
201
- )
202
- end
203
-
204
- execute do
205
- paged_enum = publisher.list_topic_subscriptions \
206
- topic_path(topic, options),
207
- page_size: options[:max],
208
- options: call_options
209
-
210
- paged_enum.page.response
211
- end
160
+ publisher.list_topic_subscriptions topic: topic_path(topic, options),
161
+ page_size: options[:max],
162
+ page_token: options[:token]
212
163
  end
213
164
 
214
165
  ##
215
166
  # Lists matching subscriptions by project.
216
167
  def list_subscriptions options = {}
217
- call_options = default_options
218
- if (token = options[:token])
219
- call_options = Google::Gax::CallOptions.new(
220
- kwargs: default_headers,
221
- page_token: token
222
- )
223
- end
168
+ paged_enum = subscriber.list_subscriptions project: project_path(options),
169
+ page_size: options[:max],
170
+ page_token: options[:token]
224
171
 
225
- execute do
226
- paged_enum = subscriber.list_subscriptions project_path(options),
227
- page_size: options[:max],
228
- options: call_options
229
-
230
- paged_enum.page.response
231
- end
172
+ paged_enum.response
232
173
  end
233
174
 
234
175
  ##
235
176
  # Creates a subscription on a given topic for a given subscriber.
236
177
  def create_subscription topic, subscription_name, options = {}
237
- name = subscription_path subscription_name, options
238
- topic = topic_path topic
239
- push_config = if options[:endpoint]
240
- Google::Cloud::PubSub::V1::PushConfig.new \
241
- push_endpoint: options[:endpoint],
242
- attributes: (options[:attributes] || {}).to_h
243
- end
244
- deadline = options[:deadline]
245
- retain_acked = options[:retain_acked]
246
- mrd = Convert.number_to_duration options[:retention]
247
- labels = options[:labels]
248
- message_ordering = options[:message_ordering]
249
- execute do
250
- subscriber.create_subscription \
251
- name, topic,
252
- push_config: push_config,
253
- ack_deadline_seconds: deadline,
254
- retain_acked_messages: retain_acked,
255
- message_retention_duration: mrd,
256
- labels: labels,
257
- enable_message_ordering: message_ordering,
258
- dead_letter_policy: dead_letter_policy(options),
259
- retry_policy: options[:retry_policy],
260
- options: default_options
261
- end
178
+ subscriber.create_subscription \
179
+ name: subscription_path(subscription_name, options),
180
+ topic: topic_path(topic),
181
+ push_config: options[:push_config],
182
+ ack_deadline_seconds: options[:deadline],
183
+ retain_acked_messages: options[:retain_acked],
184
+ message_retention_duration: Convert.number_to_duration(options[:retention]),
185
+ labels: options[:labels],
186
+ enable_message_ordering: options[:message_ordering],
187
+ filter: options[:filter],
188
+ dead_letter_policy: dead_letter_policy(options),
189
+ retry_policy: options[:retry_policy]
262
190
  end
263
191
 
264
192
  def update_subscription subscription_obj, *fields
265
193
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
266
- execute do
267
- subscriber.update_subscription subscription_obj, mask, options: default_options
268
- end
194
+ subscriber.update_subscription subscription: subscription_obj, update_mask: mask
269
195
  end
270
196
 
271
197
  ##
272
- # Deletes an existing subscription.
273
- # All pending messages in the subscription are immediately dropped.
198
+ # Deletes an existing subscription. All pending messages in the subscription are immediately dropped.
274
199
  def delete_subscription subscription
275
- execute do
276
- subscriber.delete_subscription subscription_path(subscription),
277
- options: default_options
278
- end
200
+ subscriber.delete_subscription subscription: subscription_path(subscription)
201
+ end
202
+
203
+ ##
204
+ # Detaches a subscription from its topic. All messages retained in the subscription are dropped. Subsequent
205
+ # `Pull` and `StreamingPull` requests will raise `FAILED_PRECONDITION`. If the subscription is a push
206
+ # subscription, pushes to the endpoint will stop.
207
+ def detach_subscription subscription
208
+ publisher.detach_subscription subscription: subscription_path(subscription)
279
209
  end
280
210
 
281
211
  ##
282
212
  # Pulls a single message from the server.
283
213
  def pull subscription, options = {}
284
- subscription = subscription_path subscription, options
285
214
  max_messages = options.fetch(:max, 100).to_i
286
215
  return_immediately = !(!options.fetch(:immediate, true))
287
216
 
288
- execute do
289
- subscriber.pull subscription,
290
- max_messages,
291
- return_immediately: return_immediately,
292
- options: default_options
293
- end
217
+ subscriber.pull subscription: subscription_path(subscription, options),
218
+ max_messages: max_messages,
219
+ return_immediately: return_immediately
294
220
  end
295
221
 
296
222
  def streaming_pull request_enum
297
- execute do
298
- subscriber.streaming_pull request_enum, options: default_options
299
- end
223
+ subscriber.streaming_pull request_enum
300
224
  end
301
225
 
302
226
  ##
303
227
  # Acknowledges receipt of a message.
304
228
  def acknowledge subscription, *ack_ids
305
- execute do
306
- subscriber.acknowledge subscription_path(subscription), ack_ids,
307
- options: default_options
308
- end
229
+ subscriber.acknowledge subscription: subscription_path(subscription), ack_ids: ack_ids
309
230
  end
310
231
 
311
232
  ##
312
233
  # Modifies the PushConfig for a specified subscription.
313
234
  def modify_push_config subscription, endpoint, attributes
314
- subscription = subscription_path subscription
315
235
  # Convert attributes to strings to match the protobuf definition
316
236
  attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
317
237
  push_config = Google::Cloud::PubSub::V1::PushConfig.new(
@@ -319,138 +239,83 @@ module Google
319
239
  attributes: attributes
320
240
  )
321
241
 
322
- execute do
323
- subscriber.modify_push_config subscription, push_config,
324
- options: default_options
325
- end
242
+ subscriber.modify_push_config subscription: subscription_path(subscription),
243
+ push_config: push_config
326
244
  end
327
245
 
328
246
  ##
329
247
  # Modifies the ack deadline for a specific message.
330
248
  def modify_ack_deadline subscription, ids, deadline
331
- execute do
332
- subscriber.modify_ack_deadline subscription_path(subscription),
333
- Array(ids),
334
- deadline, options: default_options
335
- end
249
+ subscriber.modify_ack_deadline subscription: subscription_path(subscription),
250
+ ack_ids: Array(ids),
251
+ ack_deadline_seconds: deadline
336
252
  end
337
253
 
338
254
  ##
339
255
  # Lists snapshots by project.
340
256
  def list_snapshots options = {}
341
- call_options = default_options
342
- if (token = options[:token])
343
- call_options = Google::Gax::CallOptions.new(
344
- kwargs: default_headers,
345
- page_token: token
346
- )
347
- end
348
-
349
- execute do
350
- paged_enum = subscriber.list_snapshots project_path(options),
351
- page_size: options[:max],
352
- options: call_options
257
+ paged_enum = subscriber.list_snapshots project: project_path(options),
258
+ page_size: options[:max],
259
+ page_token: options[:token]
353
260
 
354
- paged_enum.page.response
355
- end
261
+ paged_enum.response
356
262
  end
357
263
 
358
264
  ##
359
265
  # Creates a snapshot on a given subscription.
360
266
  def create_snapshot subscription, snapshot_name, labels: nil
361
- name = snapshot_path snapshot_name
362
- execute do
363
- subscriber.create_snapshot name,
364
- subscription_path(subscription),
365
- labels: labels,
366
- options: default_options
367
- end
267
+ subscriber.create_snapshot name: snapshot_path(snapshot_name),
268
+ subscription: subscription_path(subscription),
269
+ labels: labels
368
270
  end
369
271
 
370
272
  def update_snapshot snapshot_obj, *fields
371
273
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
372
- execute do
373
- subscriber.update_snapshot snapshot_obj, mask, options: default_options
374
- end
274
+ subscriber.update_snapshot snapshot: snapshot_obj, update_mask: mask
375
275
  end
376
276
 
377
277
  ##
378
278
  # Deletes an existing snapshot.
379
279
  # All pending messages in the snapshot are immediately dropped.
380
280
  def delete_snapshot snapshot
381
- execute do
382
- subscriber.delete_snapshot snapshot_path(snapshot),
383
- options: default_options
384
- end
281
+ subscriber.delete_snapshot snapshot: snapshot_path(snapshot)
385
282
  end
386
283
 
387
284
  ##
388
285
  # Adjusts the given subscription to a time or snapshot.
389
286
  def seek subscription, time_or_snapshot
390
- subscription = subscription_path subscription
391
- execute do
392
- if a_time? time_or_snapshot
393
- time = Convert.time_to_timestamp time_or_snapshot
394
- subscriber.seek subscription, time: time, options: default_options
395
- else
396
- time_or_snapshot = time_or_snapshot.name if time_or_snapshot.is_a? Snapshot
397
- subscriber.seek subscription,
398
- snapshot: snapshot_path(time_or_snapshot),
399
- options: default_options
400
- end
287
+ if a_time? time_or_snapshot
288
+ time = Convert.time_to_timestamp time_or_snapshot
289
+ subscriber.seek subscription: subscription, time: time
290
+ else
291
+ time_or_snapshot = time_or_snapshot.name if time_or_snapshot.is_a? Snapshot
292
+ subscriber.seek subscription: subscription_path(subscription),
293
+ snapshot: snapshot_path(time_or_snapshot)
401
294
  end
402
295
  end
403
296
 
404
297
  def get_topic_policy topic_name, options = {}
405
- execute do
406
- publisher.get_iam_policy topic_path(topic_name, options),
407
- options: default_options
408
- end
298
+ iam.get_iam_policy resource: topic_path(topic_name, options)
409
299
  end
410
300
 
411
301
  def set_topic_policy topic_name, new_policy, options = {}
412
- resource = topic_path topic_name, options
413
-
414
- execute do
415
- publisher.set_iam_policy resource, new_policy,
416
- options: default_options
417
- end
302
+ iam.set_iam_policy resource: topic_path(topic_name, options), policy: new_policy
418
303
  end
419
304
 
420
305
  def test_topic_permissions topic_name, permissions, options = {}
421
- resource = topic_path topic_name, options
422
-
423
- execute do
424
- publisher.test_iam_permissions resource, permissions,
425
- options: default_options
426
- end
306
+ iam.test_iam_permissions resource: topic_path(topic_name, options), permissions: permissions
427
307
  end
428
308
 
429
309
  def get_subscription_policy subscription_name, options = {}
430
- resource = subscription_path subscription_name, options
431
-
432
- execute do
433
- subscriber.get_iam_policy resource, options: default_options
434
- end
310
+ iam.get_iam_policy resource: subscription_path(subscription_name, options)
435
311
  end
436
312
 
437
313
  def set_subscription_policy subscription_name, new_policy, options = {}
438
- resource = subscription_path subscription_name, options
439
-
440
- execute do
441
- subscriber.set_iam_policy resource, new_policy,
442
- options: default_options
443
- end
314
+ iam.set_iam_policy resource: subscription_path(subscription_name, options), policy: new_policy
444
315
  end
445
316
 
446
- def test_subscription_permissions subscription_name,
447
- permissions, options = {}
448
- resource = subscription_path subscription_name, options
449
-
450
- execute do
451
- subscriber.test_iam_permissions resource, permissions,
452
- options: default_options
453
- end
317
+ def test_subscription_permissions subscription_name, permissions, options = {}
318
+ iam.test_iam_permissions resource: subscription_path(subscription_name, options), permissions: permissions
454
319
  end
455
320
 
456
321
  def project_path options = {}
@@ -494,21 +359,6 @@ module Google
494
359
  end
495
360
  policy
496
361
  end
497
-
498
- def default_headers
499
- { "google-cloud-resource-prefix" => "projects/#{@project}" }
500
- end
501
-
502
- def default_options
503
- Google::Gax::CallOptions.new kwargs: default_headers
504
- end
505
-
506
- def execute
507
- yield
508
- rescue Google::Gax::GaxError => e
509
- # GaxError wraps BadStatus, but exposes it as #cause
510
- raise Google::Cloud::Error.from_error(e.cause)
511
- end
512
362
  end
513
363
  end
514
364