google-cloud-pubsub 1.9.0 → 2.2.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 -257
  13. data/lib/google/cloud/pubsub/subscriber.rb +3 -3
  14. data/lib/google/cloud/pubsub/subscriber/stream.rb +1 -2
  15. data/lib/google/cloud/pubsub/subscription.rb +124 -22
  16. data/lib/google/cloud/pubsub/subscription/push_config.rb +55 -31
  17. data/lib/google/cloud/pubsub/topic.rb +50 -15
  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 -833
  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 -1466
  34. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +0 -153
  35. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -269
  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,140 +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
- mrd = Convert.number_to_duration options[:retention]
245
- execute do
246
- subscriber.create_subscription \
247
- name, topic,
248
- push_config: push_config,
249
- ack_deadline_seconds: options[:deadline],
250
- retain_acked_messages: options[:retain_acked],
251
- message_retention_duration: mrd,
252
- labels: options[:labels],
253
- enable_message_ordering: options[:message_ordering],
254
- filter: options[:filter],
255
- dead_letter_policy: dead_letter_policy(options),
256
- retry_policy: options[:retry_policy],
257
- options: default_options
258
- 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]
259
190
  end
260
191
 
261
192
  def update_subscription subscription_obj, *fields
262
193
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
263
- execute do
264
- subscriber.update_subscription subscription_obj, mask, options: default_options
265
- end
194
+ subscriber.update_subscription subscription: subscription_obj, update_mask: mask
266
195
  end
267
196
 
268
197
  ##
269
- # Deletes an existing subscription.
270
- # All pending messages in the subscription are immediately dropped.
198
+ # Deletes an existing subscription. All pending messages in the subscription are immediately dropped.
271
199
  def delete_subscription subscription
272
- execute do
273
- subscriber.delete_subscription subscription_path(subscription),
274
- options: default_options
275
- 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)
276
209
  end
277
210
 
278
211
  ##
279
212
  # Pulls a single message from the server.
280
213
  def pull subscription, options = {}
281
- subscription = subscription_path subscription, options
282
214
  max_messages = options.fetch(:max, 100).to_i
283
215
  return_immediately = !(!options.fetch(:immediate, true))
284
216
 
285
- execute do
286
- subscriber.pull subscription,
287
- max_messages,
288
- return_immediately: return_immediately,
289
- options: default_options
290
- end
217
+ subscriber.pull subscription: subscription_path(subscription, options),
218
+ max_messages: max_messages,
219
+ return_immediately: return_immediately
291
220
  end
292
221
 
293
222
  def streaming_pull request_enum
294
- execute do
295
- subscriber.streaming_pull request_enum, options: default_options
296
- end
223
+ subscriber.streaming_pull request_enum
297
224
  end
298
225
 
299
226
  ##
300
227
  # Acknowledges receipt of a message.
301
228
  def acknowledge subscription, *ack_ids
302
- execute do
303
- subscriber.acknowledge subscription_path(subscription), ack_ids,
304
- options: default_options
305
- end
229
+ subscriber.acknowledge subscription: subscription_path(subscription), ack_ids: ack_ids
306
230
  end
307
231
 
308
232
  ##
309
233
  # Modifies the PushConfig for a specified subscription.
310
234
  def modify_push_config subscription, endpoint, attributes
311
- subscription = subscription_path subscription
312
235
  # Convert attributes to strings to match the protobuf definition
313
236
  attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
314
237
  push_config = Google::Cloud::PubSub::V1::PushConfig.new(
@@ -316,138 +239,83 @@ module Google
316
239
  attributes: attributes
317
240
  )
318
241
 
319
- execute do
320
- subscriber.modify_push_config subscription, push_config,
321
- options: default_options
322
- end
242
+ subscriber.modify_push_config subscription: subscription_path(subscription),
243
+ push_config: push_config
323
244
  end
324
245
 
325
246
  ##
326
247
  # Modifies the ack deadline for a specific message.
327
248
  def modify_ack_deadline subscription, ids, deadline
328
- execute do
329
- subscriber.modify_ack_deadline subscription_path(subscription),
330
- Array(ids),
331
- deadline, options: default_options
332
- end
249
+ subscriber.modify_ack_deadline subscription: subscription_path(subscription),
250
+ ack_ids: Array(ids),
251
+ ack_deadline_seconds: deadline
333
252
  end
334
253
 
335
254
  ##
336
255
  # Lists snapshots by project.
337
256
  def list_snapshots options = {}
338
- call_options = default_options
339
- if (token = options[:token])
340
- call_options = Google::Gax::CallOptions.new(
341
- kwargs: default_headers,
342
- page_token: token
343
- )
344
- end
345
-
346
- execute do
347
- paged_enum = subscriber.list_snapshots project_path(options),
348
- page_size: options[:max],
349
- options: call_options
257
+ paged_enum = subscriber.list_snapshots project: project_path(options),
258
+ page_size: options[:max],
259
+ page_token: options[:token]
350
260
 
351
- paged_enum.page.response
352
- end
261
+ paged_enum.response
353
262
  end
354
263
 
355
264
  ##
356
265
  # Creates a snapshot on a given subscription.
357
266
  def create_snapshot subscription, snapshot_name, labels: nil
358
- name = snapshot_path snapshot_name
359
- execute do
360
- subscriber.create_snapshot name,
361
- subscription_path(subscription),
362
- labels: labels,
363
- options: default_options
364
- end
267
+ subscriber.create_snapshot name: snapshot_path(snapshot_name),
268
+ subscription: subscription_path(subscription),
269
+ labels: labels
365
270
  end
366
271
 
367
272
  def update_snapshot snapshot_obj, *fields
368
273
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
369
- execute do
370
- subscriber.update_snapshot snapshot_obj, mask, options: default_options
371
- end
274
+ subscriber.update_snapshot snapshot: snapshot_obj, update_mask: mask
372
275
  end
373
276
 
374
277
  ##
375
278
  # Deletes an existing snapshot.
376
279
  # All pending messages in the snapshot are immediately dropped.
377
280
  def delete_snapshot snapshot
378
- execute do
379
- subscriber.delete_snapshot snapshot_path(snapshot),
380
- options: default_options
381
- end
281
+ subscriber.delete_snapshot snapshot: snapshot_path(snapshot)
382
282
  end
383
283
 
384
284
  ##
385
285
  # Adjusts the given subscription to a time or snapshot.
386
286
  def seek subscription, time_or_snapshot
387
- subscription = subscription_path subscription
388
- execute do
389
- if a_time? time_or_snapshot
390
- time = Convert.time_to_timestamp time_or_snapshot
391
- subscriber.seek subscription, time: time, options: default_options
392
- else
393
- time_or_snapshot = time_or_snapshot.name if time_or_snapshot.is_a? Snapshot
394
- subscriber.seek subscription,
395
- snapshot: snapshot_path(time_or_snapshot),
396
- options: default_options
397
- 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)
398
294
  end
399
295
  end
400
296
 
401
297
  def get_topic_policy topic_name, options = {}
402
- execute do
403
- publisher.get_iam_policy topic_path(topic_name, options),
404
- options: default_options
405
- end
298
+ iam.get_iam_policy resource: topic_path(topic_name, options)
406
299
  end
407
300
 
408
301
  def set_topic_policy topic_name, new_policy, options = {}
409
- resource = topic_path topic_name, options
410
-
411
- execute do
412
- publisher.set_iam_policy resource, new_policy,
413
- options: default_options
414
- end
302
+ iam.set_iam_policy resource: topic_path(topic_name, options), policy: new_policy
415
303
  end
416
304
 
417
305
  def test_topic_permissions topic_name, permissions, options = {}
418
- resource = topic_path topic_name, options
419
-
420
- execute do
421
- publisher.test_iam_permissions resource, permissions,
422
- options: default_options
423
- end
306
+ iam.test_iam_permissions resource: topic_path(topic_name, options), permissions: permissions
424
307
  end
425
308
 
426
309
  def get_subscription_policy subscription_name, options = {}
427
- resource = subscription_path subscription_name, options
428
-
429
- execute do
430
- subscriber.get_iam_policy resource, options: default_options
431
- end
310
+ iam.get_iam_policy resource: subscription_path(subscription_name, options)
432
311
  end
433
312
 
434
313
  def set_subscription_policy subscription_name, new_policy, options = {}
435
- resource = subscription_path subscription_name, options
436
-
437
- execute do
438
- subscriber.set_iam_policy resource, new_policy,
439
- options: default_options
440
- end
314
+ iam.set_iam_policy resource: subscription_path(subscription_name, options), policy: new_policy
441
315
  end
442
316
 
443
- def test_subscription_permissions subscription_name,
444
- permissions, options = {}
445
- resource = subscription_path subscription_name, options
446
-
447
- execute do
448
- subscriber.test_iam_permissions resource, permissions,
449
- options: default_options
450
- end
317
+ def test_subscription_permissions subscription_name, permissions, options = {}
318
+ iam.test_iam_permissions resource: subscription_path(subscription_name, options), permissions: permissions
451
319
  end
452
320
 
453
321
  def project_path options = {}
@@ -491,21 +359,6 @@ module Google
491
359
  end
492
360
  policy
493
361
  end
494
-
495
- def default_headers
496
- { "google-cloud-resource-prefix" => "projects/#{@project}" }
497
- end
498
-
499
- def default_options
500
- Google::Gax::CallOptions.new kwargs: default_headers
501
- end
502
-
503
- def execute
504
- yield
505
- rescue Google::Gax::GaxError => e
506
- # GaxError wraps BadStatus, but exposes it as #cause
507
- raise Google::Cloud::Error.from_error(e.cause)
508
- end
509
362
  end
510
363
  end
511
364