google-cloud-pubsub 0.20.0 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +18 -0
  3. data/AUTHENTICATION.md +178 -0
  4. data/CHANGELOG.md +659 -0
  5. data/CODE_OF_CONDUCT.md +40 -0
  6. data/CONTRIBUTING.md +187 -0
  7. data/EMULATOR.md +37 -0
  8. data/LICENSE +201 -0
  9. data/LOGGING.md +32 -0
  10. data/OVERVIEW.md +528 -0
  11. data/TROUBLESHOOTING.md +31 -0
  12. data/lib/google/cloud/pubsub/async_publisher/batch.rb +310 -0
  13. data/lib/google/cloud/pubsub/async_publisher.rb +402 -0
  14. data/lib/google/cloud/pubsub/batch_publisher.rb +100 -0
  15. data/lib/google/cloud/pubsub/convert.rb +91 -0
  16. data/lib/google/cloud/pubsub/credentials.rb +26 -10
  17. data/lib/google/cloud/pubsub/errors.rb +85 -0
  18. data/lib/google/cloud/pubsub/message.rb +82 -20
  19. data/lib/google/cloud/pubsub/policy.rb +40 -61
  20. data/lib/google/cloud/pubsub/project.rb +405 -265
  21. data/lib/google/cloud/pubsub/publish_result.rb +103 -0
  22. data/lib/google/cloud/pubsub/received_message.rb +165 -30
  23. data/lib/google/cloud/pubsub/retry_policy.rb +88 -0
  24. data/lib/google/cloud/pubsub/schema/list.rb +180 -0
  25. data/lib/google/cloud/pubsub/schema.rb +310 -0
  26. data/lib/google/cloud/pubsub/service.rb +304 -162
  27. data/lib/google/cloud/pubsub/snapshot/list.rb +178 -0
  28. data/lib/google/cloud/pubsub/snapshot.rb +205 -0
  29. data/lib/google/cloud/pubsub/subscriber/enumerator_queue.rb +54 -0
  30. data/lib/google/cloud/pubsub/subscriber/inventory.rb +173 -0
  31. data/lib/google/cloud/pubsub/subscriber/sequencer.rb +115 -0
  32. data/lib/google/cloud/pubsub/subscriber/stream.rb +400 -0
  33. data/lib/google/cloud/pubsub/subscriber/timed_unary_buffer.rb +230 -0
  34. data/lib/google/cloud/pubsub/subscriber.rb +417 -0
  35. data/lib/google/cloud/pubsub/subscription/list.rb +38 -43
  36. data/lib/google/cloud/pubsub/subscription/push_config.rb +268 -0
  37. data/lib/google/cloud/pubsub/subscription.rb +1040 -210
  38. data/lib/google/cloud/pubsub/topic/list.rb +32 -37
  39. data/lib/google/cloud/pubsub/topic.rb +726 -177
  40. data/lib/google/cloud/pubsub/version.rb +6 -4
  41. data/lib/google/cloud/pubsub.rb +138 -413
  42. data/lib/google-cloud-pubsub.rb +60 -42
  43. metadata +88 -39
  44. data/lib/google/cloud/pubsub/topic/publisher.rb +0 -87
  45. data/lib/google/iam/v1/iam_policy.rb +0 -33
  46. data/lib/google/iam/v1/iam_policy_services.rb +0 -30
  47. data/lib/google/iam/v1/policy.rb +0 -25
  48. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -129
  49. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -117
@@ -1,10 +1,10 @@
1
- # Copyright 2015 Google Inc. All rights reserved.
1
+ # Copyright 2015 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
8
  #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,13 +13,19 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
+ require "google/cloud/pubsub/convert"
16
17
  require "google/cloud/errors"
17
18
  require "google/cloud/pubsub/subscription/list"
19
+ require "google/cloud/pubsub/subscription/push_config"
18
20
  require "google/cloud/pubsub/received_message"
21
+ require "google/cloud/pubsub/retry_policy"
22
+ require "google/cloud/pubsub/snapshot"
23
+ require "google/cloud/pubsub/subscriber"
24
+ require "google/cloud/pubsub/v1"
19
25
 
20
26
  module Google
21
27
  module Cloud
22
- module Pubsub
28
+ module PubSub
23
29
  ##
24
30
  # # Subscription
25
31
  #
@@ -27,215 +33,766 @@ module Google
27
33
  # specific {Topic}, to be delivered to the subscribing application.
28
34
  #
29
35
  # @example
30
- # require "google/cloud"
36
+ # require "google/cloud/pubsub"
31
37
  #
32
- # gcloud = Google::Cloud.new
33
- # pubsub = gcloud.pubsub
38
+ # pubsub = Google::Cloud::PubSub.new
34
39
  #
35
40
  # sub = pubsub.subscription "my-topic-sub"
36
- # msgs = sub.pull
37
- # msgs.each { |msg| msg.acknowledge! }
41
+ # subscriber = sub.listen do |received_message|
42
+ # # process message
43
+ # received_message.acknowledge!
44
+ # end
38
45
  #
46
+ # # Handle exceptions from listener
47
+ # subscriber.on_error do |exception|
48
+ # puts "Exception: #{exception.class} #{exception.message}"
49
+ # end
50
+ #
51
+ # # Gracefully shut down the subscriber
52
+ # at_exit do
53
+ # subscriber.stop!
54
+ # end
55
+ #
56
+ # # Start background threads that will call the block passed to listen.
57
+ # subscriber.start
58
+ # sleep
39
59
  class Subscription
40
60
  ##
41
- # @private The gRPC Service object.
61
+ # @private The Service object.
42
62
  attr_accessor :service
43
63
 
44
64
  ##
45
- # @private The gRPC Google::Pubsub::V1::Subscription object.
65
+ # @private The gRPC Google::Cloud::PubSub::V1::Subscription object.
46
66
  attr_accessor :grpc
47
67
 
48
68
  ##
49
69
  # @private Create an empty {Subscription} object.
50
70
  def initialize
51
71
  @service = nil
52
- @grpc = Google::Pubsub::V1::Subscription.new
53
- @name = nil
72
+ @grpc = nil
73
+ @resource_name = nil
54
74
  @exists = nil
55
75
  end
56
76
 
57
- ##
58
- # @private New lazy {Topic} object without making an HTTP request.
59
- def self.new_lazy name, service, options = {}
60
- new.tap do |s|
61
- s.grpc = nil
62
- s.service = service
63
- s.instance_variable_set "@name",
64
- service.subscription_path(name, options)
65
- end
66
- end
67
-
68
77
  ##
69
78
  # The name of the subscription.
79
+ #
80
+ # @return [String] A fully-qualified subscription name in the form
81
+ # `projects/{project_id}/subscriptions/{subscription_id}`.
82
+ #
70
83
  def name
71
- @grpc ? @grpc.name : @name
84
+ return @resource_name if reference?
85
+ @grpc.name
72
86
  end
73
87
 
74
88
  ##
75
89
  # The {Topic} from which this subscription receives messages.
76
90
  #
91
+ # Makes an API call to retrieve the topic information when called on a
92
+ # reference object. See {#reference?}.
93
+ #
77
94
  # @return [Topic]
78
95
  #
79
96
  # @example
80
- # require "google/cloud"
97
+ # require "google/cloud/pubsub"
81
98
  #
82
- # gcloud = Google::Cloud.new
83
- # pubsub = gcloud.pubsub
99
+ # pubsub = Google::Cloud::PubSub.new
84
100
  #
85
101
  # sub = pubsub.subscription "my-topic-sub"
86
102
  # sub.topic.name #=> "projects/my-project/topics/my-topic"
87
103
  #
88
104
  def topic
89
105
  ensure_grpc!
90
- Topic.new_lazy @grpc.topic, service
106
+ Topic.from_name @grpc.topic, service
91
107
  end
92
108
 
93
109
  ##
94
110
  # This value is the maximum number of seconds after a subscriber
95
111
  # receives a message before the subscriber should acknowledge the
96
112
  # message.
113
+ #
114
+ # Makes an API call to retrieve the deadline value when called on a
115
+ # reference object. See {#reference?}.
116
+ #
117
+ # @return [Integer]
97
118
  def deadline
98
119
  ensure_grpc!
99
120
  @grpc.ack_deadline_seconds
100
121
  end
101
122
 
123
+ ##
124
+ # Sets the maximum number of seconds after a subscriber
125
+ # receives a message before the subscriber should acknowledge the
126
+ # message.
127
+ #
128
+ # @param [Integer] new_deadline The new deadline value.
129
+ #
130
+ def deadline= new_deadline
131
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, ack_deadline_seconds: new_deadline
132
+ @grpc = service.update_subscription update_grpc, :ack_deadline_seconds
133
+ @resource_name = nil
134
+ end
135
+
136
+ ##
137
+ # Indicates whether to retain acknowledged messages. If `true`, then
138
+ # messages are not expunged from the subscription's backlog, even if
139
+ # they are acknowledged, until they fall out of the {#retention} window.
140
+ # Default is `false`.
141
+ #
142
+ # Makes an API call to retrieve the retain_acked value when called on a
143
+ # reference object. See {#reference?}.
144
+ #
145
+ # @return [Boolean] Returns `true` if acknowledged messages are
146
+ # retained.
147
+ #
148
+ def retain_acked
149
+ ensure_grpc!
150
+ @grpc.retain_acked_messages
151
+ end
152
+
153
+ ##
154
+ # Sets whether to retain acknowledged messages.
155
+ #
156
+ # @param [Boolean] new_retain_acked The new retain acknowledged messages
157
+ # value.
158
+ #
159
+ def retain_acked= new_retain_acked
160
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name,
161
+ retain_acked_messages: !(!new_retain_acked)
162
+ @grpc = service.update_subscription update_grpc, :retain_acked_messages
163
+ @resource_name = nil
164
+ end
165
+
166
+ ##
167
+ # How long to retain unacknowledged messages in the subscription's
168
+ # backlog, from the moment a message is published. If
169
+ # {#retain_acked} is `true`, then this also configures the retention of
170
+ # acknowledged messages, and thus configures how far back in time a
171
+ # {#seek} can be done. Cannot be more than 604,800 seconds (7 days) or
172
+ # less than 600 seconds (10 minutes). Default is 604,800 seconds (7
173
+ # days).
174
+ #
175
+ # Makes an API call to retrieve the retention value when called on a
176
+ # reference object. See {#reference?}.
177
+ #
178
+ # @return [Numeric] The message retention duration in seconds.
179
+ #
180
+ def retention
181
+ ensure_grpc!
182
+ Convert.duration_to_number @grpc.message_retention_duration
183
+ end
184
+
185
+ ##
186
+ # Sets the message retention duration in seconds.
187
+ #
188
+ # @param [Numeric] new_retention The new retention value.
189
+ #
190
+ def retention= new_retention
191
+ new_retention_duration = Convert.number_to_duration new_retention
192
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name,
193
+ message_retention_duration: new_retention_duration
194
+ @grpc = service.update_subscription update_grpc, :message_retention_duration
195
+ @resource_name = nil
196
+ end
197
+
102
198
  ##
103
199
  # Returns the URL locating the endpoint to which messages should be
104
- # pushed.
200
+ # pushed. For example, a Webhook endpoint might use
201
+ # `https://example.com/push`.
202
+ #
203
+ # Makes an API call to retrieve the endpoint value when called on a
204
+ # reference object. See {#reference?}.
205
+ #
206
+ # @return [String]
207
+ #
105
208
  def endpoint
106
209
  ensure_grpc!
107
- @grpc.push_config.push_endpoint if @grpc.push_config
210
+ @grpc.push_config&.push_endpoint
108
211
  end
109
212
 
110
213
  ##
111
214
  # Sets the URL locating the endpoint to which messages should be pushed.
215
+ # For example, a Webhook endpoint might use `https://example.com/push`.
216
+ #
217
+ # @param [String] new_endpoint The new endpoint value.
218
+ #
112
219
  def endpoint= new_endpoint
113
220
  ensure_service!
114
221
  service.modify_push_config name, new_endpoint, {}
115
- @grpc.push_config = Google::Pubsub::V1::PushConfig.new(
222
+
223
+ return if reference?
224
+
225
+ @grpc.push_config = Google::Cloud::PubSub::V1::PushConfig.new(
116
226
  push_endpoint: new_endpoint,
117
- attributes: {}
118
- ) if @grpc
227
+ attributes: {}
228
+ )
229
+ end
230
+
231
+ ##
232
+ # Inspect the Subscription's push configuration settings. The
233
+ # configuration can be changed by modifying the values in the method's
234
+ # block.
235
+ #
236
+ # Subscription objects that are reference only will return an empty
237
+ # {Subscription::PushConfig} object, which can be configured and saved
238
+ # using the method's block. Unlike {#endpoint}, which will retrieve the
239
+ # full resource from the API before returning. To get the actual values
240
+ # for a reference object, call {#reload!} before calling {#push_config}.
241
+ #
242
+ # @yield [push_config] a block for modifying the push configuration
243
+ # @yieldparam [Subscription::PushConfig] push_config the push
244
+ # configuration
245
+ #
246
+ # @return [Subscription::PushConfig]
247
+ #
248
+ # @example
249
+ # require "google/cloud/pubsub"
250
+ #
251
+ # pubsub = Google::Cloud::PubSub.new
252
+ #
253
+ # sub = pubsub.subscription "my-topic-sub"
254
+ # sub.push_config.endpoint #=> "http://example.com/callback"
255
+ # sub.push_config.authentication.email #=> "user@example.com"
256
+ # sub.push_config.authentication.audience #=> "client-12345"
257
+ #
258
+ # @example Update the push configuration by passing a block:
259
+ # require "google/cloud/pubsub"
260
+ #
261
+ # pubsub = Google::Cloud::PubSub.new
262
+ # sub = pubsub.subscription "my-subscription"
263
+ #
264
+ # sub.push_config do |pc|
265
+ # pc.endpoint = "http://example.net/callback"
266
+ # pc.set_oidc_token "user@example.net", "client-67890"
267
+ # end
268
+ #
269
+ def push_config
270
+ ensure_service!
271
+
272
+ orig_config = reference? ? nil : @grpc.push_config
273
+ config = PushConfig.from_grpc orig_config
274
+
275
+ if block_given?
276
+ old_config = config.to_grpc.dup
277
+ yield config
278
+ new_config = config.to_grpc
279
+
280
+ if old_config != new_config # has the object been changed?
281
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, push_config: new_config
282
+ @grpc = service.update_subscription update_grpc, :push_config
283
+ end
284
+ end
285
+
286
+ config.freeze
287
+ end
288
+
289
+ ##
290
+ # A hash of user-provided labels associated with this subscription.
291
+ # Labels can be used to organize and group subscriptions.See [Creating
292
+ # and Managing Labels](https://cloud.google.com/pubsub/docs/labels).
293
+ #
294
+ # The returned hash is frozen and changes are not allowed. Use
295
+ # {#labels=} to update the labels for this subscription.
296
+ #
297
+ # Makes an API call to retrieve the labels value when called on a
298
+ # reference object. See {#reference?}.
299
+ #
300
+ # @return [Hash] The frozen labels hash.
301
+ #
302
+ def labels
303
+ ensure_grpc!
304
+ @grpc.labels.to_h.freeze
305
+ end
306
+
307
+ ##
308
+ # Sets the hash of user-provided labels associated with this
309
+ # subscription. Labels can be used to organize and group subscriptions.
310
+ # Label keys and values can be no longer than 63 characters, can only
311
+ # contain lowercase letters, numeric characters, underscores and dashes.
312
+ # International characters are allowed. Label values are optional. Label
313
+ # keys must start with a letter and each label in the list must have a
314
+ # different key. See [Creating and Managing
315
+ # Labels](https://cloud.google.com/pubsub/docs/labels).
316
+ #
317
+ # @param [Hash] new_labels The new labels hash.
318
+ #
319
+ def labels= new_labels
320
+ raise ArgumentError, "Value must be a Hash" if new_labels.nil?
321
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, labels: new_labels
322
+ @grpc = service.update_subscription update_grpc, :labels
323
+ @resource_name = nil
324
+ end
325
+
326
+ ##
327
+ # The duration (in seconds) for when a subscription expires after the
328
+ # subscription goes inactive. A subscription is considered active as
329
+ # long as any connected subscriber is successfully consuming messages
330
+ # from the subscription or is issuing operations on the subscription.
331
+ #
332
+ # If {#expires_in=} is not set, a *default* value of of 31 days will be
333
+ # used. The minimum allowed value is 1 day.
334
+ #
335
+ # Makes an API call to retrieve the expires_in value when called on a
336
+ # reference object. See {#reference?}.
337
+ #
338
+ # @return [Numeric, nil] The expiration duration, or `nil` if unset.
339
+ #
340
+ def expires_in
341
+ ensure_grpc!
342
+
343
+ return nil if @grpc.expiration_policy.nil?
344
+
345
+ Convert.duration_to_number @grpc.expiration_policy.ttl
346
+ end
347
+
348
+ ##
349
+ # Sets the duration (in seconds) for when a subscription expires after
350
+ # the subscription goes inactive.
351
+ #
352
+ # See also {#expires_in}.
353
+ #
354
+ # @param [Numeric, nil] ttl The expiration duration in seconds, or `nil`
355
+ # to unset.
356
+ #
357
+ def expires_in= ttl
358
+ new_expiration_policy = Google::Cloud::PubSub::V1::ExpirationPolicy.new ttl: Convert.number_to_duration(ttl)
359
+
360
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, expiration_policy: new_expiration_policy
361
+ @grpc = service.update_subscription update_grpc, :expiration_policy
362
+ @resource_name = nil
363
+ end
364
+
365
+ ##
366
+ # An expression written in the Cloud Pub/Sub filter language. If non-empty, then only {Message} instances whose
367
+ # `attributes` field matches the filter are delivered on this subscription. If empty, then no messages are
368
+ # filtered out.
369
+ #
370
+ # Makes an API call to retrieve the filter value when called on a reference
371
+ # object. See {#reference?}.
372
+ #
373
+ # @return [String] The frozen filter string.
374
+ #
375
+ def filter
376
+ ensure_grpc!
377
+ @grpc.filter.freeze
378
+ end
379
+
380
+ ##
381
+ # Returns the {Topic} to which dead letter messages should be published if a dead letter policy is configured,
382
+ # otherwise `nil`. Dead lettering is done on a best effort basis. The same message might be dead lettered
383
+ # multiple times.
384
+ #
385
+ # See also {#dead_letter_topic=}, {#dead_letter_max_delivery_attempts=}, {#dead_letter_max_delivery_attempts}
386
+ # and {#remove_dead_letter_policy}.
387
+ #
388
+ # Makes an API call to retrieve the topic name when called on a reference object. See {#reference?}.
389
+ #
390
+ # @return [Topic, nil]
391
+ #
392
+ # @example
393
+ # require "google/cloud/pubsub"
394
+ #
395
+ # pubsub = Google::Cloud::PubSub.new
396
+ #
397
+ # sub = pubsub.subscription "my-topic-sub"
398
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
399
+ # sub.dead_letter_max_delivery_attempts #=> 10
400
+ #
401
+ def dead_letter_topic
402
+ ensure_grpc!
403
+ return nil unless @grpc.dead_letter_policy
404
+ Topic.from_name @grpc.dead_letter_policy.dead_letter_topic, service
405
+ end
406
+
407
+ ##
408
+ # Sets the {Topic} to which dead letter messages for the subscription should be published. Dead lettering is
409
+ # done on a best effort basis. The same message might be dead lettered multiple times.
410
+ # The Cloud Pub/Sub service account associated with the enclosing subscription's parent project (i.e.,
411
+ # `service-\\{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have permission to Publish() to this
412
+ # topic.
413
+ #
414
+ # The operation will fail if the topic does not exist. Users should ensure that there is a subscription attached
415
+ # to this topic since messages published to a topic with no subscriptions are lost.
416
+ #
417
+ # Makes an API call to retrieve the dead_letter_policy value when called on a
418
+ # reference object. See {#reference?}.
419
+ #
420
+ # See also {#dead_letter_topic}, {#dead_letter_max_delivery_attempts=}, {#dead_letter_max_delivery_attempts}
421
+ # and {#remove_dead_letter_policy}.
422
+ #
423
+ # @param [Topic] new_dead_letter_topic The topic to which dead letter messages for the subscription should be
424
+ # published.
425
+ #
426
+ # @example
427
+ # require "google/cloud/pubsub"
428
+ #
429
+ # pubsub = Google::Cloud::PubSub.new
430
+ #
431
+ # sub = pubsub.subscription "my-topic-sub"
432
+ # dead_letter_topic = pubsub.topic "my-dead-letter-topic", skip_lookup: true
433
+ # sub.dead_letter_topic = dead_letter_topic
434
+ #
435
+ def dead_letter_topic= new_dead_letter_topic
436
+ ensure_grpc!
437
+ dead_letter_policy = @grpc.dead_letter_policy || Google::Cloud::PubSub::V1::DeadLetterPolicy.new
438
+ dead_letter_policy.dead_letter_topic = new_dead_letter_topic.name
439
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, dead_letter_policy: dead_letter_policy
440
+ @grpc = service.update_subscription update_grpc, :dead_letter_policy
441
+ @resource_name = nil
442
+ end
443
+
444
+ ##
445
+ # Returns the maximum number of delivery attempts for any message in the subscription's dead letter policy if a
446
+ # dead letter policy is configured, otherwise `nil`. Dead lettering is done on a best effort basis. The same
447
+ # message might be dead lettered multiple times. The value must be between 5 and 100.
448
+ #
449
+ # The number of delivery attempts is defined as 1 + (the sum of number of NACKs and number of times the
450
+ # acknowledgement deadline has been exceeded for the message). A NACK is any call to ModifyAckDeadline with a 0
451
+ # deadline. Note that client libraries may automatically extend ack_deadlines.
452
+ #
453
+ # This field will be honored on a best effort basis. If this parameter is `nil` or `0`, a default value of `5`
454
+ # is used.
455
+ #
456
+ # See also {#dead_letter_max_delivery_attempts=}, {#dead_letter_topic=}, {#dead_letter_topic}
457
+ # and {#remove_dead_letter_policy}.
458
+ #
459
+ # Makes an API call to retrieve the dead_letter_policy when called on a reference object. See {#reference?}.
460
+ #
461
+ # @return [Integer, nil] A value between `5` and `100`, or `nil` if no dead letter policy is configured.
462
+ #
463
+ # @example
464
+ # require "google/cloud/pubsub"
465
+ #
466
+ # pubsub = Google::Cloud::PubSub.new
467
+ #
468
+ # sub = pubsub.subscription "my-topic-sub"
469
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
470
+ # sub.dead_letter_max_delivery_attempts #=> 10
471
+ #
472
+ def dead_letter_max_delivery_attempts
473
+ ensure_grpc!
474
+ @grpc.dead_letter_policy&.max_delivery_attempts
475
+ end
476
+
477
+ ##
478
+ # Sets the maximum number of delivery attempts for any message in the subscription's dead letter policy.
479
+ # Dead lettering is done on a best effort basis. The same message might be dead lettered multiple times.
480
+ # The value must be between 5 and 100.
481
+ #
482
+ # The number of delivery attempts is defined as 1 + (the sum of number of NACKs and number of times the
483
+ # acknowledgement deadline has been exceeded for the message). A NACK is any call to ModifyAckDeadline with a 0
484
+ # deadline. Note that client libraries may automatically extend ack_deadlines.
485
+ #
486
+ # This field will be honored on a best effort basis. If this parameter is 0, a default value of 5 is used.
487
+ #
488
+ # Makes an API call to retrieve the dead_letter_policy when called on a reference object. See {#reference?}.
489
+ #
490
+ # The dead letter topic must be set first. See {#dead_letter_topic=}, {#dead_letter_topic} and
491
+ # {#remove_dead_letter_policy}.
492
+ #
493
+ # @param [Integer, nil] new_dead_letter_max_delivery_attempts A value between 5 and 100. If this parameter is
494
+ # `nil` or `0`, a default value of 5 is used.
495
+ #
496
+ # @raise [ArgumentError] if the dead letter topic has not been set. See {#dead_letter_topic=}.
497
+ #
498
+ # @example
499
+ # require "google/cloud/pubsub"
500
+ #
501
+ # pubsub = Google::Cloud::PubSub.new
502
+ #
503
+ # sub = pubsub.subscription "my-topic-sub"
504
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
505
+ #
506
+ # sub.dead_letter_max_delivery_attempts = 20
507
+ #
508
+ def dead_letter_max_delivery_attempts= new_dead_letter_max_delivery_attempts
509
+ ensure_grpc!
510
+ unless @grpc.dead_letter_policy&.dead_letter_topic
511
+ # Service error message "3:Invalid resource name given (name=)." does not identify param.
512
+ raise ArgumentError, "dead_letter_topic is required with dead_letter_max_delivery_attempts"
513
+ end
514
+ dead_letter_policy = @grpc.dead_letter_policy || Google::Cloud::PubSub::V1::DeadLetterPolicy.new
515
+ dead_letter_policy.max_delivery_attempts = new_dead_letter_max_delivery_attempts
516
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, dead_letter_policy: dead_letter_policy
517
+ @grpc = service.update_subscription update_grpc, :dead_letter_policy
518
+ @resource_name = nil
519
+ end
520
+
521
+ ##
522
+ # Removes an existing dead letter policy. A dead letter policy specifies the conditions for dead lettering
523
+ # messages in the subscription. If a dead letter policy is not set, dead lettering is disabled.
524
+ #
525
+ # Makes an API call to retrieve the dead_letter_policy when called on a reference object. See {#reference?}.
526
+ #
527
+ # See {#dead_letter_topic}, {#dead_letter_topic=}, {#dead_letter_max_delivery_attempts} and
528
+ # {#dead_letter_max_delivery_attempts=}.
529
+ #
530
+ # @return [Boolean] `true` if an existing dead letter policy was removed, `false` if no existing dead letter
531
+ # policy was present.
532
+ #
533
+ # @example
534
+ # require "google/cloud/pubsub"
535
+ #
536
+ # pubsub = Google::Cloud::PubSub.new
537
+ #
538
+ # sub = pubsub.subscription "my-topic-sub"
539
+ #
540
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
541
+ # sub.dead_letter_max_delivery_attempts #=> 10
542
+ #
543
+ # sub.remove_dead_letter_policy
544
+ #
545
+ # sub.dead_letter_topic #=> nil
546
+ # sub.dead_letter_max_delivery_attempts #=> nil
547
+ #
548
+ def remove_dead_letter_policy
549
+ ensure_grpc!
550
+ return false if @grpc.dead_letter_policy.nil?
551
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, dead_letter_policy: nil
552
+ @grpc = service.update_subscription update_grpc, :dead_letter_policy
553
+ true
554
+ end
555
+
556
+ ##
557
+ # A policy that specifies how Cloud Pub/Sub retries message delivery for this subscription. If `nil`, the
558
+ # default retry policy is applied. This generally implies that messages will be retried as soon as possible
559
+ # for healthy subscribers. Retry Policy will be triggered on NACKs or acknowledgement deadline exceeded events
560
+ # for a given message.
561
+ #
562
+ # Makes an API call to retrieve the retry_policy when called on a reference object. See {#reference?}.
563
+ #
564
+ # @return [RetryPolicy, nil] The retry policy for the subscription, or `nil`.
565
+ #
566
+ # @example
567
+ # require "google/cloud/pubsub"
568
+ #
569
+ # pubsub = Google::Cloud::PubSub.new
570
+ #
571
+ # sub = pubsub.subscription "my-topic-sub"
572
+ #
573
+ # sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
574
+ #
575
+ # sub.retry_policy.minimum_backoff #=> 5
576
+ # sub.retry_policy.maximum_backoff #=> 300
577
+ #
578
+ def retry_policy
579
+ ensure_grpc!
580
+ return nil unless @grpc.retry_policy
581
+ RetryPolicy.from_grpc @grpc.retry_policy
582
+ end
583
+
584
+ ##
585
+ # Sets a policy that specifies how Cloud Pub/Sub retries message delivery for this subscription. If `nil`, the
586
+ # default retry policy is applied. This generally implies that messages will be retried as soon as possible
587
+ # for healthy subscribers. Retry Policy will be triggered on NACKs or acknowledgement deadline exceeded events
588
+ # for a given message.
589
+ #
590
+ # @param [RetryPolicy, nil] new_retry_policy A new retry policy for the subscription, or `nil`.
591
+ #
592
+ # @example
593
+ # require "google/cloud/pubsub"
594
+ #
595
+ # pubsub = Google::Cloud::PubSub.new
596
+ #
597
+ # sub = pubsub.subscription "my-topic-sub"
598
+ #
599
+ # sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
600
+ #
601
+ # sub.retry_policy.minimum_backoff #=> 5
602
+ # sub.retry_policy.maximum_backoff #=> 300
603
+ #
604
+ def retry_policy= new_retry_policy
605
+ ensure_service!
606
+ new_retry_policy = new_retry_policy.to_grpc if new_retry_policy
607
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, retry_policy: new_retry_policy
608
+ @grpc = service.update_subscription update_grpc, :retry_policy
609
+ @resource_name = nil
610
+ end
611
+
612
+ ##
613
+ # Whether message ordering has been enabled. When enabled, messages
614
+ # published with the same `ordering_key` will be delivered in the order
615
+ # they were published. When disabled, messages may be delivered in any
616
+ # order.
617
+ #
618
+ # @note At the time of this release, ordering keys are not yet publicly
619
+ # enabled and requires special project enablements.
620
+ #
621
+ # See {Topic#publish_async}, {#listen}, and {Message#ordering_key}.
622
+ #
623
+ # Makes an API call to retrieve the enable_message_ordering value when called on a
624
+ # reference object. See {#reference?}.
625
+ #
626
+ # @return [Boolean]
627
+ #
628
+ def message_ordering?
629
+ ensure_grpc!
630
+ @grpc.enable_message_ordering
631
+ end
632
+
633
+ ##
634
+ # Whether the subscription is detached from its topic. Detached subscriptions don't receive messages from their
635
+ # topic and don't retain any backlog. {#pull} and {#listen} (pull and streaming pull) operations will raise
636
+ # `FAILED_PRECONDITION`. If the subscription is a push subscription (see {#push_config}), pushes to the endpoint
637
+ # will not be made. The default value is `false`.
638
+ #
639
+ # See {Topic#subscribe} and {#detach}.
640
+ #
641
+ # Makes an API call to retrieve the detached value when called on a
642
+ # reference object. See {#reference?}.
643
+ #
644
+ # @return [Boolean]
645
+ #
646
+ # @example
647
+ # require "google/cloud/pubsub"
648
+ #
649
+ # pubsub = Google::Cloud::PubSub.new
650
+ #
651
+ # sub = pubsub.subscription "my-topic-sub"
652
+ # sub.detach
653
+ #
654
+ # # sleep 120
655
+ # sub.detached? #=> true
656
+ #
657
+ def detached?
658
+ ensure_grpc!
659
+ @grpc.detached
119
660
  end
120
661
 
121
662
  ##
122
663
  # Determines whether the subscription exists in the Pub/Sub service.
123
664
  #
665
+ # Makes an API call to determine whether the subscription resource
666
+ # exists when called on a reference object. See {#reference?}.
667
+ #
668
+ # @return [Boolean]
669
+ #
124
670
  # @example
125
- # require "google/cloud"
671
+ # require "google/cloud/pubsub"
126
672
  #
127
- # gcloud = Google::Cloud.new
128
- # pubsub = gcloud.pubsub
673
+ # pubsub = Google::Cloud::PubSub.new
129
674
  #
130
675
  # sub = pubsub.subscription "my-topic-sub"
131
676
  # sub.exists? #=> true
132
677
  #
133
678
  def exists?
134
- # Always true if we have a grpc object
135
- return true unless @grpc.nil?
679
+ # Always true if the object is not set as reference
680
+ return true unless reference?
136
681
  # If we have a value, return it
137
682
  return @exists unless @exists.nil?
138
683
  ensure_grpc!
139
- @exists = !@grpc.nil?
684
+ @exists = true
140
685
  rescue Google::Cloud::NotFoundError
141
686
  @exists = false
142
687
  end
143
688
 
144
689
  ##
145
- # @private
146
- # Determines whether the subscription object was created with an
147
- # HTTP call.
690
+ # Deletes an existing subscription.
691
+ # All pending messages in the subscription are immediately dropped.
692
+ #
693
+ # @return [Boolean] Returns `true` if the subscription was deleted.
148
694
  #
149
695
  # @example
150
- # require "google/cloud"
696
+ # require "google/cloud/pubsub"
151
697
  #
152
- # gcloud = Google::Cloud.new
153
- # pubsub = gcloud.pubsub
698
+ # pubsub = Google::Cloud::PubSub.new
154
699
  #
155
- # sub = pubsub.get_subscription "my-topic-sub"
156
- # sub.lazy? #=> false
700
+ # sub = pubsub.subscription "my-topic-sub"
701
+ # sub.delete
157
702
  #
158
- def lazy?
159
- @grpc.nil?
703
+ def delete
704
+ ensure_service!
705
+ service.delete_subscription name
706
+ true
160
707
  end
161
708
 
162
709
  ##
163
- # Deletes an existing subscription.
164
- # All pending messages in the subscription are immediately dropped.
710
+ # Detaches a subscription from its topic. All messages retained in the subscription are dropped. Detached
711
+ # subscriptions don't receive messages from their topic and don't retain any backlog. Subsequent {#pull} and
712
+ # {#listen} (pull and streaming pull) operations will raise `FAILED_PRECONDITION`. If the subscription is a push
713
+ # subscription (see {#push_config}), pushes to the endpoint will stop. It may take a few minutes for the
714
+ # subscription's detached state to be reflected in subsequent calls to {#detached?}.
165
715
  #
166
- # @return [Boolean] Returns `true` if the subscription was deleted.
716
+ # @return [Boolean] Returns `true` if the detach operation was successful.
167
717
  #
168
718
  # @example
169
- # require "google/cloud"
719
+ # require "google/cloud/pubsub"
170
720
  #
171
- # gcloud = Google::Cloud.new
172
- # pubsub = gcloud.pubsub
721
+ # pubsub = Google::Cloud::PubSub.new
173
722
  #
174
723
  # sub = pubsub.subscription "my-topic-sub"
175
- # sub.delete
724
+ # sub.detach
176
725
  #
177
- def delete
726
+ # # sleep 120
727
+ # sub.detached? #=> true
728
+ #
729
+ def detach
178
730
  ensure_service!
179
- service.delete_subscription name
731
+ service.detach_subscription name
180
732
  true
181
733
  end
182
734
 
183
735
  ##
184
- # Pulls messages from the server. Returns an empty list if there are no
185
- # messages available in the backlog. Raises an ApiError with status
186
- # `UNAVAILABLE` if there are too many concurrent pull requests pending
187
- # for the given subscription.
736
+ # Pulls messages from the server, blocking until messages are available
737
+ # when called with the `immediate: false` option, which is recommended
738
+ # to avoid adverse impacts on the performance of pull operations.
739
+ #
740
+ # Raises an API error with status `UNAVAILABLE` if there are too many
741
+ # concurrent pull requests pending for the given subscription.
742
+ #
743
+ # See also {#listen} for the preferred way to process messages as they
744
+ # become available.
188
745
  #
189
- # @param [Boolean] immediate When `true` the system will respond
190
- # immediately even if it is not able to return messages. When `false`
191
- # the system is allowed to wait until it can return least one message.
192
- # No messages are returned when a request times out. The default value
193
- # is `true`.
746
+ # @param [Boolean] immediate Whether to return immediately or block until
747
+ # messages are available.
748
+ #
749
+ # **Warning:** The default value of this field is `true`. However, sending
750
+ # `true` is discouraged because it adversely impacts the performance of
751
+ # pull operations. We recommend that users always explicitly set this field
752
+ # to `false`.
753
+ #
754
+ # If this field set to `true`, the system will respond immediately
755
+ # even if it there are no messages available to return in the pull
756
+ # response. Otherwise, the system may wait (for a bounded amount of time)
757
+ # until at least one message is available, rather than returning no messages.
758
+ #
759
+ # See also {#listen} for the preferred way to process messages as they
760
+ # become available.
194
761
  # @param [Integer] max The maximum number of messages to return for this
195
762
  # request. The Pub/Sub system may return fewer than the number
196
763
  # specified. The default value is `100`, the maximum value is `1000`.
197
- # @param [Boolean] autoack Automatically acknowledge the message as it
198
- # is pulled. The default value is `false`.
199
764
  #
200
- # @return [Array<Google::Cloud::Pubsub::ReceivedMessage>]
765
+ # @return [Array<Google::Cloud::PubSub::ReceivedMessage>]
201
766
  #
202
- # @example
203
- # require "google/cloud"
767
+ # @example The `immediate: false` option is now recommended to avoid adverse impacts on pull operations:
768
+ # require "google/cloud/pubsub"
204
769
  #
205
- # gcloud = Google::Cloud.new
206
- # pubsub = gcloud.pubsub
770
+ # pubsub = Google::Cloud::PubSub.new
207
771
  #
208
772
  # sub = pubsub.subscription "my-topic-sub"
209
- # sub.pull.each { |msg| msg.acknowledge! }
773
+ # received_messages = sub.pull immediate: false
774
+ # received_messages.each do |received_message|
775
+ # received_message.acknowledge!
776
+ # end
210
777
  #
211
778
  # @example A maximum number of messages returned can also be specified:
212
- # require "google/cloud"
213
- #
214
- # gcloud = Google::Cloud.new
215
- # pubsub = gcloud.pubsub
779
+ # require "google/cloud/pubsub"
216
780
  #
217
- # sub = pubsub.subscription "my-topic-sub", max: 10
218
- # sub.pull.each { |msg| msg.acknowledge! }
219
- #
220
- # @example The call can block until messages are available:
221
- # require "google/cloud"
222
- #
223
- # gcloud = Google::Cloud.new
224
- # pubsub = gcloud.pubsub
781
+ # pubsub = Google::Cloud::PubSub.new
225
782
  #
226
783
  # sub = pubsub.subscription "my-topic-sub"
227
- # msgs = sub.pull immediate: false
228
- # msgs.each { |msg| msg.acknowledge! }
784
+ # received_messages = sub.pull immediate: false, max: 10
785
+ # received_messages.each do |received_message|
786
+ # received_message.acknowledge!
787
+ # end
229
788
  #
230
- def pull immediate: true, max: 100, autoack: false
789
+ def pull immediate: true, max: 100
231
790
  ensure_service!
232
791
  options = { immediate: immediate, max: max }
233
792
  list_grpc = service.pull name, options
234
- messages = Array(list_grpc.received_messages).map do |msg_grpc|
793
+ Array(list_grpc.received_messages).map do |msg_grpc|
235
794
  ReceivedMessage.from_grpc msg_grpc, self
236
795
  end
237
- acknowledge messages if autoack
238
- messages
239
796
  rescue Google::Cloud::DeadlineExceededError
240
797
  []
241
798
  end
@@ -246,86 +803,194 @@ module Google
246
803
  #
247
804
  # subscription.pull immediate: false
248
805
  #
806
+ # See also {#listen} for the preferred way to process messages as they
807
+ # become available.
808
+ #
249
809
  # @param [Integer] max The maximum number of messages to return for this
250
810
  # request. The Pub/Sub system may return fewer than the number
251
811
  # specified. The default value is `100`, the maximum value is `1000`.
252
- # @param [Boolean] autoack Automatically acknowledge the message as it
253
- # is pulled. The default value is `false`.
254
812
  #
255
- # @return [Array<Google::Cloud::Pubsub::ReceivedMessage>]
813
+ # @return [Array<Google::Cloud::PubSub::ReceivedMessage>]
256
814
  #
257
815
  # @example
258
- # require "google/cloud"
816
+ # require "google/cloud/pubsub"
259
817
  #
260
- # gcloud = Google::Cloud.new
261
- # pubsub = gcloud.pubsub
818
+ # pubsub = Google::Cloud::PubSub.new
262
819
  #
263
820
  # sub = pubsub.subscription "my-topic-sub"
264
- # msgs = sub.wait_for_messages
265
- # msgs.each { |msg| msg.acknowledge! }
821
+ # received_messages = sub.wait_for_messages
822
+ # received_messages.each do |received_message|
823
+ # received_message.acknowledge!
824
+ # end
266
825
  #
267
- def wait_for_messages max: 100, autoack: false
268
- pull immediate: false, max: max, autoack: autoack
826
+ def wait_for_messages max: 100
827
+ pull immediate: false, max: max
269
828
  end
270
829
 
271
830
  ##
272
- # Poll the backend for new messages. This runs a loop to ping the API,
273
- # blocking indefinitely, yielding retrieved messages as they are
274
- # received.
275
- #
276
- # @param [Integer] max The maximum number of messages to return for this
277
- # request. The Pub/Sub system may return fewer than the number
278
- # specified. The default value is `100`, the maximum value is `1000`.
279
- # @param [Boolean] autoack Automatically acknowledge the message as it
280
- # is pulled. The default value is `false`.
281
- # @param [Number] delay The number of seconds to pause between requests
282
- # when the Google Cloud service has no messages to return. The default
283
- # value is `1`.
284
- # @yield [msg] a block for processing new messages
285
- # @yieldparam [ReceivedMessage] msg the newly received message
831
+ # Create a {Subscriber} object that receives and processes messages
832
+ # using the code provided in the callback. Messages passed to the
833
+ # callback should acknowledge ({ReceivedMessage#acknowledge!}) or reject
834
+ # ({ReceivedMessage#reject!}) the message. If no action is taken, the
835
+ # message will be removed from the subscriber and made available for
836
+ # redelivery after the callback is completed.
837
+ #
838
+ # Google Cloud Pub/Sub ordering keys provide the ability to ensure
839
+ # related messages are sent to subscribers in the order in which they
840
+ # were published. Messages can be tagged with an ordering key, a string
841
+ # that identifies related messages for which publish order should be
842
+ # respected. The service guarantees that, for a given ordering key and
843
+ # publisher, messages are sent to subscribers in the order in which they
844
+ # were published. Ordering does not require sacrificing high throughput
845
+ # or scalability, as the service automatically distributes messages for
846
+ # different ordering keys across subscribers.
847
+ #
848
+ # To use ordering keys, the subscription must be created with message
849
+ # ordering enabled (See {Topic#subscribe} and {#message_ordering?})
850
+ # before calling {#listen}. When enabled, the subscriber will deliver
851
+ # messages with the same `ordering_key` in the order they were
852
+ # published.
853
+ #
854
+ # @note At the time of this release, ordering keys are not yet publicly
855
+ # enabled and requires special project enablements.
856
+ #
857
+ # @param [Numeric] deadline The default number of seconds the stream
858
+ # will hold received messages before modifying the message's ack
859
+ # deadline. The minimum is 10, the maximum is 600. Default is
860
+ # {#deadline}. Optional.
861
+ #
862
+ # When using a reference object an API call will be made to retrieve
863
+ # the default deadline value for the subscription when this argument
864
+ # is not provided. See {#reference?}.
865
+ # @param [Boolean] message_ordering Whether message ordering has been
866
+ # enabled. The value provided must match the value set on the Pub/Sub
867
+ # service. See {#message_ordering?}. Optional.
868
+ #
869
+ # When using a reference object an API call will be made to retrieve
870
+ # the default message_ordering value for the subscription when this
871
+ # argument is not provided. See {#reference?}.
872
+ # @param [Integer] streams The number of concurrent streams to open to
873
+ # pull messages from the subscription. Default is 4. Optional.
874
+ # @param [Hash, Integer] inventory The settings to control how received messages are to be handled by the
875
+ # subscriber. When provided as an Integer instead of a Hash only `max_outstanding_messages` will be set.
876
+ # Optional.
877
+ #
878
+ # Hash keys and values may include the following:
879
+ #
880
+ # * `:max_outstanding_messages` [Integer] The number of received messages to be collected by subscriber.
881
+ # Default is 1,000. (Note: replaces `:limit`, which is deprecated.)
882
+ # * `:max_outstanding_bytes` [Integer] The total byte size of received messages to be collected by
883
+ # subscriber. Default is 100,000,000 (100MB). (Note: replaces `:bytesize`, which is deprecated.)
884
+ # * `:use_legacy_flow_control` [Boolean] Disables enforcing flow control settings at the Cloud PubSub
885
+ # server and the less accurate method of only enforcing flow control at the client side is used instead.
886
+ # Default is false.
887
+ # * `:max_total_lease_duration` [Integer] The number of seconds that received messages can be held awaiting
888
+ # processing. Default is 3,600 (1 hour). (Note: replaces `:extension`, which is deprecated.)
889
+ # * `:max_duration_per_lease_extension` [Integer] The maximum amount of time in seconds for a single lease
890
+ # extension attempt. Bounds the delay before a message redelivery if the subscriber fails to extend the
891
+ # deadline. Default is 0 (disabled).
892
+ # @param [Hash] threads The number of threads to create to handle
893
+ # concurrent calls by each stream opened by the subscriber. Optional.
894
+ #
895
+ # Hash keys and values may include the following:
896
+ #
897
+ # * `:callback` (Integer) The number of threads used to handle the
898
+ # received messages. Default is 8.
899
+ # * `:push` (Integer) The number of threads to handle
900
+ # acknowledgement ({ReceivedMessage#ack!}) and modify ack deadline
901
+ # messages ({ReceivedMessage#nack!},
902
+ # {ReceivedMessage#modify_ack_deadline!}). Default is 4.
903
+ #
904
+ # @yield [received_message] a block for processing new messages
905
+ # @yieldparam [ReceivedMessage] received_message the newly received
906
+ # message
907
+ #
908
+ # @return [Subscriber]
286
909
  #
287
910
  # @example
288
- # require "google/cloud"
911
+ # require "google/cloud/pubsub"
289
912
  #
290
- # gcloud = Google::Cloud.new
291
- # pubsub = gcloud.pubsub
913
+ # pubsub = Google::Cloud::PubSub.new
292
914
  #
293
915
  # sub = pubsub.subscription "my-topic-sub"
294
- # sub.listen do |msg|
295
- # # process msg
916
+ #
917
+ # subscriber = sub.listen do |received_message|
918
+ # # process message
919
+ # puts "Data: #{received_message.message.data}, published at #{received_message.message.published_at}"
920
+ # received_message.acknowledge!
296
921
  # end
297
922
  #
298
- # @example Limit number of messages pulled per API request with `max`:
299
- # require "google/cloud"
923
+ # # Start background threads that will call block passed to listen.
924
+ # subscriber.start
925
+ #
926
+ # # Shut down the subscriber when ready to stop receiving messages.
927
+ # subscriber.stop!
928
+ #
929
+ # @example Configuring to increase concurrent callbacks:
930
+ # require "google/cloud/pubsub"
300
931
  #
301
- # gcloud = Google::Cloud.new
302
- # pubsub = gcloud.pubsub
932
+ # pubsub = Google::Cloud::PubSub.new
303
933
  #
304
934
  # sub = pubsub.subscription "my-topic-sub"
305
- # sub.listen max: 20 do |msg|
306
- # # process msg
935
+ #
936
+ # subscriber = sub.listen threads: { callback: 16 } do |rec_message|
937
+ # # store the message somewhere before acknowledging
938
+ # store_in_backend rec_message.data # takes a few seconds
939
+ # rec_message.acknowledge!
940
+ # end
941
+ #
942
+ # # Start background threads that will call block passed to listen.
943
+ # subscriber.start
944
+ #
945
+ # # Shut down the subscriber when ready to stop receiving messages.
946
+ # subscriber.stop!
947
+ #
948
+ # @example Ordered messages are supported using ordering_key:
949
+ # require "google/cloud/pubsub"
950
+ #
951
+ # pubsub = Google::Cloud::PubSub.new
952
+ #
953
+ # sub = pubsub.subscription "my-ordered-topic-sub"
954
+ # sub.message_ordering? #=> true
955
+ #
956
+ # subscriber = sub.listen do |received_message|
957
+ # # messsages with the same ordering_key are received
958
+ # # in the order in which they were published.
959
+ # received_message.acknowledge!
307
960
  # end
308
961
  #
309
- # @example Automatically acknowledge messages with `autoack`:
310
- # require "google/cloud"
962
+ # # Start background threads that will call block passed to listen.
963
+ # subscriber.start
311
964
  #
312
- # gcloud = Google::Cloud.new
313
- # pubsub = gcloud.pubsub
965
+ # # Shut down the subscriber when ready to stop receiving messages.
966
+ # subscriber.stop!
967
+ #
968
+ # @example Set the maximum amount of time before redelivery if the subscriber fails to extend the deadline:
969
+ # require "google/cloud/pubsub"
970
+ #
971
+ # pubsub = Google::Cloud::PubSub.new
314
972
  #
315
973
  # sub = pubsub.subscription "my-topic-sub"
316
- # sub.listen autoack: true do |msg|
317
- # # process msg
974
+ #
975
+ # subscriber = sub.listen inventory: { max_duration_per_lease_extension: 20 } do |received_message|
976
+ # # Process message very slowly with possibility of failure.
977
+ # process rec_message.data # takes minutes
978
+ # rec_message.acknowledge!
318
979
  # end
319
980
  #
320
- def listen max: 100, autoack: false, delay: 1
321
- loop do
322
- msgs = wait_for_messages max: max, autoack: autoack
323
- if msgs.any?
324
- msgs.each { |msg| yield msg }
325
- else
326
- sleep delay
327
- end
328
- end
981
+ # # Start background threads that will call block passed to listen.
982
+ # subscriber.start
983
+ #
984
+ # # Shut down the subscriber when ready to stop receiving messages.
985
+ # subscriber.stop!
986
+ #
987
+ def listen deadline: nil, message_ordering: nil, streams: nil, inventory: nil, threads: {}, &block
988
+ ensure_service!
989
+ deadline ||= self.deadline
990
+ message_ordering = message_ordering? if message_ordering.nil?
991
+
992
+ Subscriber.new name, block, deadline: deadline, streams: streams, inventory: inventory,
993
+ message_ordering: message_ordering, threads: threads, service: service
329
994
  end
330
995
 
331
996
  ##
@@ -336,18 +1001,19 @@ module Google
336
1001
  # Acknowledging a message more than once will not result in an error.
337
1002
  # This is only used for messages received via pull.
338
1003
  #
1004
+ # See also {ReceivedMessage#acknowledge!}.
1005
+ #
339
1006
  # @param [ReceivedMessage, String] messages One or more
340
1007
  # {ReceivedMessage} objects or ack_id values.
341
1008
  #
342
1009
  # @example
343
- # require "google/cloud"
1010
+ # require "google/cloud/pubsub"
344
1011
  #
345
- # gcloud = Google::Cloud.new
346
- # pubsub = gcloud.pubsub
1012
+ # pubsub = Google::Cloud::PubSub.new
347
1013
  #
348
1014
  # sub = pubsub.subscription "my-topic-sub"
349
- # messages = sub.pull
350
- # sub.acknowledge messages
1015
+ # received_messages = sub.pull immediate: false
1016
+ # sub.acknowledge received_messages
351
1017
  #
352
1018
  def acknowledge *messages
353
1019
  ack_ids = coerce_ack_ids messages
@@ -356,7 +1022,7 @@ module Google
356
1022
  service.acknowledge name, *ack_ids
357
1023
  true
358
1024
  end
359
- alias_method :ack, :acknowledge
1025
+ alias ack acknowledge
360
1026
 
361
1027
  ##
362
1028
  # Modifies the acknowledge deadline for messages.
@@ -365,6 +1031,8 @@ module Google
365
1031
  # make the messages available for redelivery if the processing was
366
1032
  # interrupted.
367
1033
  #
1034
+ # See also {ReceivedMessage#modify_ack_deadline!}.
1035
+ #
368
1036
  # @param [Integer] new_deadline The new ack deadline in seconds from the
369
1037
  # time this request is sent to the Pub/Sub system. Must be >= 0. For
370
1038
  # example, if the value is `10`, the new ack deadline will expire 10
@@ -374,34 +1042,200 @@ module Google
374
1042
  # {ReceivedMessage} objects or ack_id values.
375
1043
  #
376
1044
  # @example
377
- # require "google/cloud"
1045
+ # require "google/cloud/pubsub"
378
1046
  #
379
- # gcloud = Google::Cloud.new
380
- # pubsub = gcloud.pubsub
1047
+ # pubsub = Google::Cloud::PubSub.new
381
1048
  #
382
1049
  # sub = pubsub.subscription "my-topic-sub"
383
- # messages = sub.pull
384
- # sub.delay 120, messages
1050
+ # received_messages = sub.pull immediate: false
1051
+ # sub.modify_ack_deadline 120, received_messages
385
1052
  #
386
- def delay new_deadline, *messages
1053
+ def modify_ack_deadline new_deadline, *messages
387
1054
  ack_ids = coerce_ack_ids messages
388
1055
  ensure_service!
389
1056
  service.modify_ack_deadline name, ack_ids, new_deadline
390
1057
  true
391
1058
  end
392
1059
 
1060
+ ##
1061
+ # Creates a new {Snapshot} from the subscription. The created snapshot
1062
+ # is guaranteed to retain:
1063
+ #
1064
+ # * The existing backlog on the subscription. More precisely, this is
1065
+ # defined as the messages in the subscription's backlog that are
1066
+ # unacknowledged upon the successful completion of the
1067
+ # `create_snapshot` operation; as well as:
1068
+ # * Any messages published to the subscription's topic following the
1069
+ # successful completion of the `create_snapshot` operation.
1070
+ #
1071
+ # @param [String, nil] snapshot_name Name of the new snapshot. Optional.
1072
+ # If the name is not provided, the server will assign a random name
1073
+ # for this snapshot on the same project as the subscription.
1074
+ # The value can be a simple snapshot ID (relative name), in which
1075
+ # case the current project ID will be supplied, or a fully-qualified
1076
+ # snapshot name in the form
1077
+ # `projects/{project_id}/snapshots/{snapshot_id}`.
1078
+ #
1079
+ # The snapshot ID (relative name) must start with a letter, and
1080
+ # contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),
1081
+ # underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent
1082
+ # signs (`%`). It must be between 3 and 255 characters in length, and
1083
+ # it must not start with `goog`.
1084
+ # @param [Hash] labels A hash of user-provided labels associated with
1085
+ # the snapshot. You can use these to organize and group your
1086
+ # snapshots. Label keys and values can be no longer than 63
1087
+ # characters, can only contain lowercase letters, numeric characters,
1088
+ # underscores and dashes. International characters are allowed. Label
1089
+ # values are optional. Label keys must start with a letter and each
1090
+ # label in the list must have a different key. See [Creating and
1091
+ # Managing Labels](https://cloud.google.com/pubsub/docs/labels).
1092
+ #
1093
+ # @return [Google::Cloud::PubSub::Snapshot]
1094
+ #
1095
+ # @example
1096
+ # require "google/cloud/pubsub"
1097
+ #
1098
+ # pubsub = Google::Cloud::PubSub.new
1099
+ # sub = pubsub.subscription "my-sub"
1100
+ #
1101
+ # snapshot = sub.create_snapshot "my-snapshot"
1102
+ # snapshot.name #=> "projects/my-project/snapshots/my-snapshot"
1103
+ #
1104
+ # @example Without providing a name:
1105
+ # require "google/cloud/pubsub"
1106
+ #
1107
+ # pubsub = Google::Cloud::PubSub.new
1108
+ # sub = pubsub.subscription "my-sub"
1109
+ #
1110
+ # snapshot = sub.create_snapshot
1111
+ # snapshot.name #=> "projects/my-project/snapshots/gcr-analysis-..."
1112
+ #
1113
+ def create_snapshot snapshot_name = nil, labels: nil
1114
+ ensure_service!
1115
+ grpc = service.create_snapshot name, snapshot_name, labels: labels
1116
+ Snapshot.from_grpc grpc, service
1117
+ end
1118
+ alias new_snapshot create_snapshot
1119
+
1120
+ ##
1121
+ # Resets the subscription's backlog to a given {Snapshot} or to a point
1122
+ # in time, whichever is provided in the request.
1123
+ #
1124
+ # @param [Snapshot, String, Time] snapshot The `Snapshot` instance,
1125
+ # snapshot name, or time to which to perform the seek.
1126
+ # If the argument is a snapshot, the snapshot's topic must be the
1127
+ # same as that of the subscription. If it is a time, messages retained
1128
+ # in the subscription that were published before this time are marked
1129
+ # as acknowledged, and messages retained in the subscription that were
1130
+ # published after this time are marked as unacknowledged. Note that
1131
+ # this operation affects only those messages retained in the
1132
+ # subscription. For example, if the time corresponds to a point before
1133
+ # the message retention window (or to a point before the system's
1134
+ # notion of the subscription creation time), only retained messages
1135
+ # will be marked as unacknowledged, and already-expunged messages will
1136
+ # not be restored.
1137
+ #
1138
+ # @return [Boolean] Returns `true` if the seek was successful.
1139
+ #
1140
+ # @example Using a snapshot
1141
+ # require "google/cloud/pubsub"
1142
+ #
1143
+ # pubsub = Google::Cloud::PubSub.new
1144
+ # sub = pubsub.subscription "my-sub"
1145
+ #
1146
+ # snapshot = sub.create_snapshot
1147
+ #
1148
+ # received_messages = sub.pull immediate: false
1149
+ # sub.acknowledge received_messages
1150
+ #
1151
+ # sub.seek snapshot
1152
+ #
1153
+ # @example Using a time:
1154
+ # require "google/cloud/pubsub"
1155
+ #
1156
+ # pubsub = Google::Cloud::PubSub.new
1157
+ # sub = pubsub.subscription "my-sub"
1158
+ #
1159
+ # time = Time.now
1160
+ #
1161
+ # received_messages = sub.pull immediate: false
1162
+ # sub.acknowledge received_messages
1163
+ #
1164
+ # sub.seek time
1165
+ #
1166
+ def seek snapshot
1167
+ ensure_service!
1168
+ service.seek name, snapshot
1169
+ true
1170
+ end
1171
+
1172
+ ##
1173
+ # Determines whether the subscription object was created without
1174
+ # retrieving the resource representation from the Pub/Sub service.
1175
+ #
1176
+ # @return [Boolean] `true` when the subscription was created without a
1177
+ # resource representation, `false` otherwise.
1178
+ #
1179
+ # @example
1180
+ # require "google/cloud/pubsub"
1181
+ #
1182
+ # pubsub = Google::Cloud::PubSub.new
1183
+ #
1184
+ # sub = pubsub.get_subscription "my-topic-sub", skip_lookup: true
1185
+ # sub.reference? #=> true
1186
+ #
1187
+ def reference?
1188
+ @grpc.nil?
1189
+ end
1190
+
1191
+ ##
1192
+ # Determines whether the subscription object was created with a resource
1193
+ # representation from the Pub/Sub service.
1194
+ #
1195
+ # @return [Boolean] `true` when the subscription was created with a
1196
+ # resource representation, `false` otherwise.
1197
+ #
1198
+ # @example
1199
+ # require "google/cloud/pubsub"
1200
+ #
1201
+ # pubsub = Google::Cloud::PubSub.new
1202
+ #
1203
+ # sub = pubsub.get_subscription "my-topic-sub"
1204
+ # sub.resource? #=> true
1205
+ #
1206
+ def resource?
1207
+ !@grpc.nil?
1208
+ end
1209
+
1210
+ ##
1211
+ # Reloads the subscription with current data from the Pub/Sub service.
1212
+ #
1213
+ # @return [Google::Cloud::PubSub::Subscription] Returns the reloaded
1214
+ # subscription
1215
+ #
1216
+ # @example
1217
+ # require "google/cloud/pubsub"
1218
+ #
1219
+ # pubsub = Google::Cloud::PubSub.new
1220
+ #
1221
+ # sub = pubsub.get_subscription "my-topic-sub"
1222
+ # sub.reload!
1223
+ #
1224
+ def reload!
1225
+ ensure_service!
1226
+ @grpc = service.get_subscription name
1227
+ @resource_name = nil
1228
+ self
1229
+ end
1230
+ alias refresh! reload!
1231
+
393
1232
  ##
394
1233
  # Gets the [Cloud IAM](https://cloud.google.com/iam/) access control
395
1234
  # policy for this subscription.
396
1235
  #
397
- # @see https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#iampolicy
1236
+ # @see https://cloud.google.com/pubsub/docs/reference/rpc/google.iam.v1#iampolicy
398
1237
  # google.iam.v1.IAMPolicy
399
1238
  #
400
- # @param [Boolean] force Force the latest policy to be retrieved from
401
- # the Pub/Sub service when `true`. Otherwise the policy will be
402
- # memoized to reduce the number of API calls made to the Pub/Sub
403
- # service. The default is `false`.
404
- #
405
1239
  # @yield [policy] A block for updating the policy. The latest policy
406
1240
  # will be read from the Pub/Sub service and passed to the block. After
407
1241
  # the block completes, the modified policy will be written to the
@@ -411,83 +1245,68 @@ module Google
411
1245
  #
412
1246
  # @return [Policy] the current Cloud IAM Policy for this subscription
413
1247
  #
414
- # @example Policy values are memoized to reduce the number of API calls:
415
- # require "google/cloud"
416
- #
417
- # gcloud = Google::Cloud.new
418
- # pubsub = gcloud.pubsub
419
- # sub = pubsub.subscription "my-subscription"
420
- #
421
- # policy = sub.policy # API call
422
- # policy_2 = sub.policy # No API call
423
- #
424
- # @example Use `force` to retrieve the latest policy from the service:
425
- # require "google/cloud"
1248
+ # @example
1249
+ # require "google/cloud/pubsub"
426
1250
  #
427
- # gcloud = Google::Cloud.new
428
- # pubsub = gcloud.pubsub
1251
+ # pubsub = Google::Cloud::PubSub.new
429
1252
  # sub = pubsub.subscription "my-subscription"
430
1253
  #
431
- # policy = sub.policy force: true # API call
432
- # policy_2 = sub.policy force: true # API call
1254
+ # policy = sub.policy
433
1255
  #
434
1256
  # @example Update the policy by passing a block:
435
- # require "google/cloud"
1257
+ # require "google/cloud/pubsub"
436
1258
  #
437
- # gcloud = Google::Cloud.new
438
- # pubsub = gcloud.pubsub
1259
+ # pubsub = Google::Cloud::PubSub.new
439
1260
  # sub = pubsub.subscription "my-subscription"
440
1261
  #
441
- # policy = sub.policy do |p|
1262
+ # sub.policy do |p|
442
1263
  # p.add "roles/owner", "user:owner@example.com"
443
- # end # 2 API calls
444
- #
445
- def policy force: nil
446
- @policy = nil if force || block_given?
447
- @policy ||= begin
448
- ensure_service!
449
- grpc = service.get_subscription_policy name
450
- Policy.from_grpc grpc
451
- end
452
- return @policy unless block_given?
453
- p = @policy.deep_dup
454
- yield p
455
- self.policy = p
1264
+ # end
1265
+ #
1266
+ def policy
1267
+ ensure_service!
1268
+ grpc = service.get_subscription_policy name
1269
+ policy = Policy.from_grpc grpc
1270
+ return policy unless block_given?
1271
+ yield policy
1272
+ update_policy policy
456
1273
  end
457
1274
 
458
1275
  ##
459
1276
  # Updates the [Cloud IAM](https://cloud.google.com/iam/) access control
460
1277
  # policy for this subscription. The policy should be read from
461
- # {#policy}. See {Google::Cloud::Pubsub::Policy} for an explanation of
1278
+ # {#policy}. See {Google::Cloud::PubSub::Policy} for an explanation of
462
1279
  # the policy `etag` property and how to modify policies.
463
1280
  #
464
1281
  # You can also update the policy by passing a block to {#policy}, which
465
1282
  # will call this method internally after the block completes.
466
1283
  #
467
- # @see https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#iampolicy
1284
+ # @see https://cloud.google.com/pubsub/docs/reference/rpc/google.iam.v1#iampolicy
468
1285
  # google.iam.v1.IAMPolicy
469
1286
  #
470
1287
  # @param [Policy] new_policy a new or modified Cloud IAM Policy for this
471
1288
  # subscription
472
1289
  #
1290
+ # @return [Policy] the policy returned by the API update operation
1291
+ #
473
1292
  # @example
474
- # require "google/cloud"
1293
+ # require "google/cloud/pubsub"
475
1294
  #
476
- # gcloud = Google::Cloud.new
477
- # pubsub = gcloud.pubsub
1295
+ # pubsub = Google::Cloud::PubSub.new
478
1296
  # sub = pubsub.subscription "my-subscription"
479
1297
  #
480
1298
  # policy = sub.policy # API call
481
1299
  #
482
1300
  # policy.add "roles/owner", "user:owner@example.com"
483
1301
  #
484
- # sub.policy = policy # API call
1302
+ # sub.update_policy policy # API call
485
1303
  #
486
- def policy= new_policy
1304
+ def update_policy new_policy
487
1305
  ensure_service!
488
1306
  grpc = service.set_subscription_policy name, new_policy.to_grpc
489
- @policy = Policy.from_grpc grpc
1307
+ Policy.from_grpc grpc
490
1308
  end
1309
+ alias policy= update_policy
491
1310
 
492
1311
  ##
493
1312
  # Tests the specified permissions against the [Cloud
@@ -512,10 +1331,9 @@ module Google
512
1331
  # @return [Array<String>] The permissions that have access.
513
1332
  #
514
1333
  # @example
515
- # require "google/cloud"
1334
+ # require "google/cloud/pubsub"
516
1335
  #
517
- # gcloud = Google::Cloud.new
518
- # pubsub = gcloud.pubsub
1336
+ # pubsub = Google::Cloud::PubSub.new
519
1337
  # sub = pubsub.subscription "my-subscription"
520
1338
  # perms = sub.test_permissions "pubsub.subscriptions.get",
521
1339
  # "pubsub.subscriptions.consume"
@@ -530,7 +1348,8 @@ module Google
530
1348
  end
531
1349
 
532
1350
  ##
533
- # @private New Subscription from a Google::Pubsub::V1::Subscription
1351
+ # @private
1352
+ # New Subscription from a Google::Cloud::PubSub::V1::Subscription
534
1353
  # object.
535
1354
  def self.from_grpc grpc, service
536
1355
  new.tap do |f|
@@ -539,21 +1358,30 @@ module Google
539
1358
  end
540
1359
  end
541
1360
 
1361
+ ##
1362
+ # @private New reference {Subscription} object without making an HTTP
1363
+ # request.
1364
+ def self.from_name name, service, options = {}
1365
+ name = service.subscription_path name, options
1366
+ from_grpc(nil, service).tap do |s|
1367
+ s.instance_variable_set :@resource_name, name
1368
+ end
1369
+ end
1370
+
542
1371
  protected
543
1372
 
544
1373
  ##
545
1374
  # @private Raise an error unless an active connection to the service is
546
1375
  # available.
547
1376
  def ensure_service!
548
- fail "Must have active connection to service" unless service
1377
+ raise "Must have active connection to service" unless service
549
1378
  end
550
1379
 
551
1380
  ##
552
- # Ensures a Google::Pubsub::V1::Subscription object exists.
1381
+ # Ensures a Google::Cloud::PubSub::V1::Subscription object exists.
553
1382
  def ensure_grpc!
554
1383
  ensure_service!
555
- return @grpc if @grpc
556
- @grpc = service.get_subscription @name
1384
+ reload! if reference?
557
1385
  end
558
1386
 
559
1387
  ##
@@ -566,5 +1394,7 @@ module Google
566
1394
  end
567
1395
  end
568
1396
  end
1397
+
1398
+ Pubsub = PubSub unless const_defined? :Pubsub
569
1399
  end
570
1400
  end