google-cloud-pubsub 1.1.3 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +122 -0
  3. data/EMULATOR.md +1 -1
  4. data/TROUBLESHOOTING.md +2 -8
  5. data/lib/google/cloud/pubsub/async_publisher.rb +15 -19
  6. data/lib/google/cloud/pubsub/project.rb +18 -26
  7. data/lib/google/cloud/pubsub/received_message.rb +38 -0
  8. data/lib/google/cloud/pubsub/retry_policy.rb +90 -0
  9. data/lib/google/cloud/pubsub/service.rb +37 -15
  10. data/lib/google/cloud/pubsub/subscriber/inventory.rb +43 -15
  11. data/lib/google/cloud/pubsub/subscriber/stream.rb +7 -8
  12. data/lib/google/cloud/pubsub/subscriber.rb +86 -15
  13. data/lib/google/cloud/pubsub/subscription/push_config.rb +2 -2
  14. data/lib/google/cloud/pubsub/subscription.rb +296 -6
  15. data/lib/google/cloud/pubsub/topic.rb +65 -2
  16. data/lib/google/cloud/pubsub/v1/credentials.rb +1 -1
  17. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/iam_policy.rb +1 -1
  18. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/options.rb +1 -1
  19. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/policy.rb +1 -1
  20. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +1 -1
  21. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/empty.rb +1 -1
  22. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +1 -1
  23. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +1 -1
  24. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +168 -79
  25. data/lib/google/cloud/pubsub/v1/doc/google/type/expr.rb +1 -1
  26. data/lib/google/cloud/pubsub/v1/publisher_client.rb +175 -33
  27. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +16 -1
  28. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +145 -64
  29. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +12 -3
  30. data/lib/google/cloud/pubsub/version.rb +1 -1
  31. data/lib/google/pubsub/v1/pubsub_pb.rb +20 -0
  32. data/lib/google/pubsub/v1/pubsub_services_pb.rb +7 -3
  33. metadata +6 -5
@@ -181,8 +181,8 @@ module Google
181
181
  synchronize do
182
182
  return true if @inventory.empty?
183
183
 
184
- @subscriber.buffer.renew_lease @subscriber.deadline,
185
- @inventory.ack_ids
184
+ @inventory.remove_expired!
185
+ @subscriber.buffer.renew_lease @subscriber.deadline, @inventory.ack_ids
186
186
  unpause_streaming!
187
187
  end
188
188
 
@@ -243,17 +243,13 @@ module Google
243
243
  # Cannot syncronize the enumerator, causes deadlock
244
244
  response = enum.next
245
245
 
246
- # Create a list of all the received ack_id values
247
- received_ack_ids = response.received_messages.map(&:ack_id)
248
-
249
246
  # Use synchronize so both changes happen atomically
250
247
  synchronize do
251
248
  # Create receipt of received messages reception
252
- @subscriber.buffer.modify_ack_deadline @subscriber.deadline,
253
- received_ack_ids
249
+ @subscriber.buffer.modify_ack_deadline @subscriber.deadline, response.received_messages.map(&:ack_id)
254
250
 
255
251
  # Add received messages to inventory
256
- @inventory.add received_ack_ids
252
+ @inventory.add response.received_messages
257
253
  end
258
254
 
259
255
  response.received_messages.each do |rec_msg_grpc|
@@ -367,6 +363,9 @@ module Google
367
363
  req.stream_ack_deadline_seconds = @subscriber.deadline
368
364
  req.modify_deadline_ack_ids += @inventory.ack_ids
369
365
  req.modify_deadline_seconds += @inventory.ack_ids.map { @subscriber.deadline }
366
+ req.client_id = @subscriber.service.client_id
367
+ req.max_outstanding_messages = @inventory.limit
368
+ req.max_outstanding_bytes = @inventory.bytesize
370
369
  end
371
370
  end
372
371
 
@@ -54,8 +54,6 @@ module Google
54
54
  # been enabled.
55
55
  # @attr_reader [Integer] streams The number of concurrent streams to open
56
56
  # to pull messages from the subscription. Default is 4.
57
- # @attr_reader [Integer] inventory The number of received messages to be
58
- # collected by subscriber. Default is 1,000.
59
57
  # @attr_reader [Integer] callback_threads The number of threads used to
60
58
  # handle the received messages. Default is 8.
61
59
  # @attr_reader [Integer] push_threads The number of threads to handle
@@ -66,19 +64,16 @@ module Google
66
64
  class Subscriber
67
65
  include MonitorMixin
68
66
 
69
- attr_reader :subscription_name, :callback, :deadline, :streams,
70
- :inventory, :message_ordering, :callback_threads,
67
+ attr_reader :subscription_name, :callback, :deadline, :streams, :message_ordering, :callback_threads,
71
68
  :push_threads
72
69
 
73
70
  ##
74
71
  # @private Implementation attributes.
75
- attr_reader :stream_inventory, :stream_pool, :thread_pool, :buffer,
76
- :service
72
+ attr_reader :stream_pool, :thread_pool, :buffer, :service
77
73
 
78
74
  ##
79
75
  # @private Create an empty {Subscriber} object.
80
- def initialize subscription_name, callback, deadline: nil,
81
- message_ordering: nil, streams: nil, inventory: nil,
76
+ def initialize subscription_name, callback, deadline: nil, message_ordering: nil, streams: nil, inventory: nil,
82
77
  threads: {}, service: nil
83
78
  super() # to init MonitorMixin
84
79
 
@@ -86,17 +81,15 @@ module Google
86
81
  @error_callbacks = []
87
82
  @subscription_name = subscription_name
88
83
  @deadline = deadline || 60
89
- @streams = streams || 4
90
- @inventory = inventory || 1000
84
+ @streams = streams || 2
85
+ coerce_inventory inventory
91
86
  @message_ordering = message_ordering
92
- @callback_threads = (threads[:callback] || 8).to_i
93
- @push_threads = (threads[:push] || 4).to_i
87
+ @callback_threads = Integer(threads[:callback] || 8)
88
+ @push_threads = Integer(threads[:push] || 4)
94
89
 
95
- @stream_inventory = @inventory.fdiv(@streams).ceil
96
90
  @service = service
97
91
 
98
- @started = nil
99
- @stopped = nil
92
+ @started = @stopped = nil
100
93
 
101
94
  stream_pool = Array.new @streams do
102
95
  Thread.new { Stream.new self }
@@ -111,6 +104,7 @@ module Google
111
104
  # received messages.
112
105
  #
113
106
  # @return [Subscriber] returns self so calls can be chained.
107
+ #
114
108
  def start
115
109
  start_pool = synchronize do
116
110
  @started = true
@@ -136,6 +130,7 @@ module Google
136
130
  # received messages have been processed or released.
137
131
  #
138
132
  # @return [Subscriber] returns self so calls can be chained.
133
+ #
139
134
  def stop
140
135
  stop_pool = synchronize do
141
136
  @started = false
@@ -165,6 +160,7 @@ module Google
165
160
  # subscriber is fully stopped. Default will block indefinitely.
166
161
  #
167
162
  # @return [Subscriber] returns self so calls can be chained.
163
+ #
168
164
  def wait! timeout = nil
169
165
  wait_pool = synchronize do
170
166
  @stream_pool.map do |stream|
@@ -197,6 +193,7 @@ module Google
197
193
  # Whether the subscriber has been started.
198
194
  #
199
195
  # @return [boolean] `true` when started, `false` otherwise.
196
+ #
200
197
  def started?
201
198
  synchronize { @started }
202
199
  end
@@ -205,6 +202,7 @@ module Google
205
202
  # Whether the subscriber has been stopped.
206
203
  #
207
204
  # @return [boolean] `true` when stopped, `false` otherwise.
205
+ #
208
206
  def stopped?
209
207
  synchronize { @stopped }
210
208
  end
@@ -284,6 +282,62 @@ module Google
284
282
  synchronize { @last_error }
285
283
  end
286
284
 
285
+ ##
286
+ # The number of received messages to be collected by subscriber. Default is 1,000.
287
+ #
288
+ # @return [Integer] The maximum number of messages.
289
+ #
290
+ def max_outstanding_messages
291
+ @inventory[:max_outstanding_messages]
292
+ end
293
+ # @deprecated Use {#max_outstanding_messages}.
294
+ alias inventory_limit max_outstanding_messages
295
+ # @deprecated Use {#max_outstanding_messages}.
296
+ alias inventory max_outstanding_messages
297
+
298
+ ##
299
+ # The total byte size of received messages to be collected by subscriber. Default is 100,000,000 (100MB).
300
+ #
301
+ # @return [Integer] The maximum number of bytes.
302
+ #
303
+ def max_outstanding_bytes
304
+ @inventory[:max_outstanding_bytes]
305
+ end
306
+ # @deprecated Use {#max_outstanding_bytes}.
307
+ alias inventory_bytesize max_outstanding_bytes
308
+
309
+ ##
310
+ # The number of seconds that received messages can be held awaiting processing. Default is 3,600 (1 hour).
311
+ #
312
+ # @return [Integer] The maximum number of seconds.
313
+ #
314
+ def max_total_lease_duration
315
+ @inventory[:max_total_lease_duration]
316
+ end
317
+ # @deprecated Use {#max_total_lease_duration}.
318
+ alias inventory_extension max_total_lease_duration
319
+
320
+ ##
321
+ # The maximum amount of time in seconds for a single lease extension attempt. Bounds the delay before a message
322
+ # redelivery if the subscriber fails to extend the deadline. Default is 0 (disabled).
323
+ #
324
+ # @return [Integer] The maximum number of seconds.
325
+ #
326
+ def max_duration_per_lease_extension
327
+ @inventory[:max_duration_per_lease_extension]
328
+ end
329
+
330
+ ##
331
+ # @private
332
+ def stream_inventory
333
+ {
334
+ limit: @inventory[:max_outstanding_messages].fdiv(@streams).ceil,
335
+ bytesize: @inventory[:max_outstanding_bytes].fdiv(@streams).ceil,
336
+ extension: @inventory[:max_total_lease_duration],
337
+ max_duration_per_lease_extension: @inventory[:max_duration_per_lease_extension]
338
+ }
339
+ end
340
+
287
341
  # @private returns error object from the stream thread.
288
342
  def error! error
289
343
  error_callbacks = synchronize do
@@ -308,6 +362,23 @@ module Google
308
362
 
309
363
  protected
310
364
 
365
+ def coerce_inventory inventory
366
+ @inventory = inventory
367
+ if @inventory.is_a? Hash
368
+ @inventory = @inventory.dup
369
+ # Support deprecated field names
370
+ @inventory[:max_outstanding_messages] ||= @inventory.delete :limit
371
+ @inventory[:max_outstanding_bytes] ||= @inventory.delete :bytesize
372
+ @inventory[:max_total_lease_duration] ||= @inventory.delete :extension
373
+ else
374
+ @inventory = { max_outstanding_messages: @inventory }
375
+ end
376
+ @inventory[:max_outstanding_messages] = Integer(@inventory[:max_outstanding_messages] || 1000)
377
+ @inventory[:max_outstanding_bytes] = Integer(@inventory[:max_outstanding_bytes] || 100_000_000)
378
+ @inventory[:max_total_lease_duration] = Integer(@inventory[:max_total_lease_duration] || 3600)
379
+ @inventory[:max_duration_per_lease_extension] = Integer(@inventory[:max_duration_per_lease_extension] || 0)
380
+ end
381
+
311
382
  def default_error_callbacks
312
383
  # This is memoized to reduce calls to the configuration.
313
384
  @default_error_callbacks ||= begin
@@ -52,7 +52,7 @@ module Google
52
52
 
53
53
  ##
54
54
  # A URL locating the endpoint to which messages should be pushed. For
55
- # example, a Webhook endpoint might use "https://example.com/push".
55
+ # example, a Webhook endpoint might use `https://example.com/push`.
56
56
  #
57
57
  # @return [String]
58
58
  def endpoint
@@ -62,7 +62,7 @@ module Google
62
62
  ##
63
63
  # Sets the URL locating the endpoint to which messages should be
64
64
  # pushed. For example, a Webhook endpoint might use
65
- # "https://example.com/push".
65
+ # `https://example.com/push`.
66
66
  #
67
67
  # @param [String, nil] new_endpoint New URL value
68
68
  def endpoint= new_endpoint
@@ -18,8 +18,10 @@ require "google/cloud/errors"
18
18
  require "google/cloud/pubsub/subscription/list"
19
19
  require "google/cloud/pubsub/subscription/push_config"
20
20
  require "google/cloud/pubsub/received_message"
21
+ require "google/cloud/pubsub/retry_policy"
21
22
  require "google/cloud/pubsub/snapshot"
22
23
  require "google/cloud/pubsub/subscriber"
24
+ require "google/cloud/pubsub/v1"
23
25
 
24
26
  module Google
25
27
  module Cloud
@@ -187,7 +189,7 @@ module Google
187
189
  ##
188
190
  # Returns the URL locating the endpoint to which messages should be
189
191
  # pushed. For example, a Webhook endpoint might use
190
- # "https://example.com/push".
192
+ # `https://example.com/push`.
191
193
  #
192
194
  # Makes an API call to retrieve the endpoint value when called on a
193
195
  # reference object. See {#reference?}.
@@ -201,7 +203,7 @@ module Google
201
203
 
202
204
  ##
203
205
  # Sets the URL locating the endpoint to which messages should be pushed.
204
- # For example, a Webhook endpoint might use "https://example.com/push".
206
+ # For example, a Webhook endpoint might use `https://example.com/push`.
205
207
  #
206
208
  # @param [String] new_endpoint The new endpoint value.
207
209
  #
@@ -321,7 +323,7 @@ module Google
321
323
  # If {#expires_in=} is not set, a *default* value of of 31 days will be
322
324
  # used. The minimum allowed value is 1 day.
323
325
  #
324
- # Makes an API call to retrieve the labels value when called on a
326
+ # Makes an API call to retrieve the value when called on a
325
327
  # reference object. See {#reference?}.
326
328
  #
327
329
  # @return [Numeric, nil] The expiration duration, or `nil` if unset.
@@ -351,6 +353,208 @@ module Google
351
353
  @resource_name = nil
352
354
  end
353
355
 
356
+ ##
357
+ # An expression written in the Cloud Pub/Sub filter language. If non-empty, then only {Message} instances whose
358
+ # `attributes` field matches the filter are delivered on this subscription. If empty, then no messages are
359
+ # filtered out.
360
+ #
361
+ # @return [String] The frozen filter string.
362
+ #
363
+ def filter
364
+ ensure_grpc!
365
+ @grpc.filter.freeze
366
+ end
367
+
368
+ ##
369
+ # Returns the {Topic} to which dead letter messages should be published if a dead letter policy is configured,
370
+ # otherwise `nil`. Dead lettering is done on a best effort basis. The same message might be dead lettered
371
+ # multiple times.
372
+ #
373
+ # See also {#dead_letter_topic=}, {#dead_letter_max_delivery_attempts=} and
374
+ # {#dead_letter_max_delivery_attempts}.
375
+ #
376
+ # Makes an API call to retrieve the topic name when called on a reference object. See {#reference?}.
377
+ #
378
+ # @return [Topic, nil]
379
+ #
380
+ # @example
381
+ # require "google/cloud/pubsub"
382
+ #
383
+ # pubsub = Google::Cloud::PubSub.new
384
+ #
385
+ # sub = pubsub.subscription "my-topic-sub"
386
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
387
+ # sub.dead_letter_max_delivery_attempts #=> 10
388
+ #
389
+ def dead_letter_topic
390
+ ensure_grpc!
391
+ return nil unless @grpc.dead_letter_policy
392
+ Topic.from_name @grpc.dead_letter_policy.dead_letter_topic, service
393
+ end
394
+
395
+ ##
396
+ # Sets the {Topic} to which dead letter messages for the subscription should be published. Dead lettering is
397
+ # done on a best effort basis. The same message might be dead lettered multiple times.
398
+ # The Cloud Pub/Sub service account associated with the enclosing subscription's parent project (i.e.,
399
+ # `service-\\{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have permission to Publish() to this
400
+ # topic.
401
+ #
402
+ # The operation will fail if the topic does not exist. Users should ensure that there is a subscription attached
403
+ # to this topic since messages published to a topic with no subscriptions are lost.
404
+ #
405
+ # See also {#dead_letter_topic}, {#dead_letter_max_delivery_attempts=} and {#dead_letter_max_delivery_attempts}.
406
+ #
407
+ # @param [Topic] new_dead_letter_topic The topic to which dead letter messages for the subscription should be
408
+ # published.
409
+ #
410
+ # @example
411
+ # require "google/cloud/pubsub"
412
+ #
413
+ # pubsub = Google::Cloud::PubSub.new
414
+ #
415
+ # sub = pubsub.subscription "my-topic-sub"
416
+ # dead_letter_topic = pubsub.topic "my-dead-letter-topic", skip_lookup: true
417
+ # sub.dead_letter_topic = dead_letter_topic
418
+ #
419
+ def dead_letter_topic= new_dead_letter_topic
420
+ ensure_grpc!
421
+ dead_letter_policy = @grpc.dead_letter_policy || Google::Cloud::PubSub::V1::DeadLetterPolicy.new
422
+ dead_letter_policy.dead_letter_topic = new_dead_letter_topic.name
423
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, dead_letter_policy: dead_letter_policy
424
+ @grpc = service.update_subscription update_grpc, :dead_letter_policy
425
+ @resource_name = nil
426
+ end
427
+
428
+ ##
429
+ # Returns the maximum number of delivery attempts for any message in the subscription's dead letter policy if a
430
+ # dead letter policy is configured, otherwise `nil`. Dead lettering is done on a best effort basis. The same
431
+ # message might be dead lettered multiple times. The value must be between 5 and 100.
432
+ #
433
+ # The number of delivery attempts is defined as 1 + (the sum of number of NACKs and number of times the
434
+ # acknowledgement deadline has been exceeded for the message). A NACK is any call to ModifyAckDeadline with a 0
435
+ # deadline. Note that client libraries may automatically extend ack_deadlines.
436
+ #
437
+ # This field will be honored on a best effort basis. If this parameter is 0, a default value of 5 is used.
438
+ #
439
+ # See also {#dead_letter_max_delivery_attempts=}, {#dead_letter_topic=} and {#dead_letter_topic}.
440
+ #
441
+ # Makes an API call to retrieve the value when called on a reference object. See {#reference?}.
442
+ #
443
+ # @return [Integer, nil] A value between 5 and 100, or `nil` if no dead letter policy is configured. If this
444
+ # value is 0, a default value of 5 is used.
445
+ #
446
+ # @example
447
+ # require "google/cloud/pubsub"
448
+ #
449
+ # pubsub = Google::Cloud::PubSub.new
450
+ #
451
+ # sub = pubsub.subscription "my-topic-sub"
452
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
453
+ # sub.dead_letter_max_delivery_attempts #=> 10
454
+ #
455
+ def dead_letter_max_delivery_attempts
456
+ ensure_grpc!
457
+ @grpc.dead_letter_policy&.max_delivery_attempts
458
+ end
459
+
460
+ ##
461
+ # Sets the maximum number of delivery attempts for any message in the subscription's dead letter policy.
462
+ # Dead lettering is done on a best effort basis. The same message might be dead lettered multiple times.
463
+ # The value must be between 5 and 100.
464
+ #
465
+ # The number of delivery attempts is defined as 1 + (the sum of number of NACKs and number of times the
466
+ # acknowledgement deadline has been exceeded for the message). A NACK is any call to ModifyAckDeadline with a 0
467
+ # deadline. Note that client libraries may automatically extend ack_deadlines.
468
+ #
469
+ # This field will be honored on a best effort basis. If this parameter is 0, a default value of 5 is used.
470
+ #
471
+ # The dead letter topic must also be set. See {#dead_letter_topic=} and {#dead_letter_topic}.
472
+ #
473
+ # @param [Integer] new_dead_letter_max_delivery_attempts A value between 5 and 100. If this parameter is 0, a
474
+ # default value of 5 is used.
475
+ #
476
+ # @example
477
+ # require "google/cloud/pubsub"
478
+ #
479
+ # pubsub = Google::Cloud::PubSub.new
480
+ #
481
+ # sub = pubsub.subscription "my-topic-sub"
482
+ # sub.dead_letter_topic.name #=> "projects/my-project/topics/my-dead-letter-topic"
483
+ #
484
+ # sub.dead_letter_max_delivery_attempts = 20
485
+ #
486
+ def dead_letter_max_delivery_attempts= new_dead_letter_max_delivery_attempts
487
+ ensure_grpc!
488
+ unless @grpc.dead_letter_policy&.dead_letter_topic
489
+ # Service error message "3:Invalid resource name given (name=)." does not identify param.
490
+ raise ArgumentError, "dead_letter_topic is required with dead_letter_max_delivery_attempts"
491
+ end
492
+ dead_letter_policy = @grpc.dead_letter_policy || Google::Cloud::PubSub::V1::DeadLetterPolicy.new
493
+ dead_letter_policy.max_delivery_attempts = new_dead_letter_max_delivery_attempts
494
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, dead_letter_policy: dead_letter_policy
495
+ @grpc = service.update_subscription update_grpc, :dead_letter_policy
496
+ @resource_name = nil
497
+ end
498
+
499
+ ##
500
+ # A policy that specifies how Cloud Pub/Sub retries message delivery for this subscription. If `nil`, the
501
+ # default retry policy is applied. This generally implies that messages will be retried as soon as possible
502
+ # for healthy subscribers. Retry Policy will be triggered on NACKs or acknowledgement deadline exceeded events
503
+ # for a given message.
504
+ #
505
+ # **EXPERIMENTAL:** This API might be changed in backward-incompatible ways and is not recommended for
506
+ # production use. It is not subject to any SLA or deprecation policy.
507
+ #
508
+ # @return [RetryPolicy, nil] The retry policy for the subscription, or `nil`.
509
+ #
510
+ # @example
511
+ # require "google/cloud/pubsub"
512
+ #
513
+ # pubsub = Google::Cloud::PubSub.new
514
+ #
515
+ # sub = pubsub.subscription "my-topic-sub"
516
+ #
517
+ # sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
518
+ #
519
+ # sub.retry_policy.minimum_backoff #=> 5
520
+ # sub.retry_policy.maximum_backoff #=> 300
521
+ #
522
+ def retry_policy
523
+ ensure_grpc!
524
+ return nil unless @grpc.retry_policy
525
+ RetryPolicy.from_grpc @grpc.retry_policy
526
+ end
527
+
528
+ ##
529
+ # Sets a policy that specifies how Cloud Pub/Sub retries message delivery for this subscription. If `nil`, the
530
+ # default retry policy is applied. This generally implies that messages will be retried as soon as possible
531
+ # for healthy subscribers. Retry Policy will be triggered on NACKs or acknowledgement deadline exceeded events
532
+ # for a given message.
533
+ #
534
+ # **EXPERIMENTAL:** This API might be changed in backward-incompatible ways and is not recommended for
535
+ # production use. It is not subject to any SLA or deprecation policy.
536
+ #
537
+ # @param [RetryPolicy, nil] new_retry_policy A new retry policy for the subscription, or `nil`.
538
+ #
539
+ # @example
540
+ # require "google/cloud/pubsub"
541
+ #
542
+ # pubsub = Google::Cloud::PubSub.new
543
+ #
544
+ # sub = pubsub.subscription "my-topic-sub"
545
+ #
546
+ # sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
547
+ #
548
+ # sub.retry_policy.minimum_backoff #=> 5
549
+ # sub.retry_policy.maximum_backoff #=> 300
550
+ #
551
+ def retry_policy= new_retry_policy
552
+ ensure_grpc!
553
+ new_retry_policy = new_retry_policy.to_grpc if new_retry_policy
554
+ update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, retry_policy: new_retry_policy
555
+ @grpc = service.update_subscription update_grpc, :retry_policy
556
+ end
557
+
354
558
  ##
355
559
  # Whether message ordering has been enabled. When enabled, messages
356
560
  # published with the same `ordering_key` will be delivered in the order
@@ -362,7 +566,7 @@ module Google
362
566
  #
363
567
  # See {Topic#publish_async}, {#listen}, and {Message#ordering_key}.
364
568
  #
365
- # Makes an API call to retrieve the retain_acked value when called on a
569
+ # Makes an API call to retrieve the enable_message_ordering value when called on a
366
570
  # reference object. See {#reference?}.
367
571
  #
368
572
  # @return [Boolean]
@@ -372,6 +576,35 @@ module Google
372
576
  @grpc.enable_message_ordering
373
577
  end
374
578
 
579
+ ##
580
+ # Whether the subscription is detached from its topic. Detached subscriptions don't receive messages from their
581
+ # topic and don't retain any backlog. {#pull} and {#listen} (pull and streaming pull) operations will raise
582
+ # `FAILED_PRECONDITION`. If the subscription is a push subscription (see {#push_config}), pushes to the endpoint
583
+ # will not be made. The default value is `false`.
584
+ #
585
+ # See {Topic#subscribe} and {#detach}.
586
+ #
587
+ # Makes an API call to retrieve the value when called on a
588
+ # reference object. See {#reference?}.
589
+ #
590
+ # @return [Boolean]
591
+ #
592
+ # @example
593
+ # require "google/cloud/pubsub"
594
+ #
595
+ # pubsub = Google::Cloud::PubSub.new
596
+ #
597
+ # sub = pubsub.subscription "my-topic-sub"
598
+ # sub.detach
599
+ #
600
+ # # sleep 120
601
+ # sub.detached? #=> true
602
+ #
603
+ def detached?
604
+ ensure_grpc!
605
+ @grpc.detached
606
+ end
607
+
375
608
  ##
376
609
  # Determines whether the subscription exists in the Pub/Sub service.
377
610
  #
@@ -419,6 +652,32 @@ module Google
419
652
  true
420
653
  end
421
654
 
655
+ ##
656
+ # Detaches a subscription from its topic. All messages retained in the subscription are dropped. Detached
657
+ # subscriptions don't receive messages from their topic and don't retain any backlog. Subsequent {#pull} and
658
+ # {#listen} (pull and streaming pull) operations will raise `FAILED_PRECONDITION`. If the subscription is a push
659
+ # subscription (see {#push_config}), pushes to the endpoint will stop. It may take a few minutes for the
660
+ # subscription's detached state to be reflected in subsequent calls to {#detached?}.
661
+ #
662
+ # @return [Boolean] Returns `true` if the detach operation was successful.
663
+ #
664
+ # @example
665
+ # require "google/cloud/pubsub"
666
+ #
667
+ # pubsub = Google::Cloud::PubSub.new
668
+ #
669
+ # sub = pubsub.subscription "my-topic-sub"
670
+ # sub.detach
671
+ #
672
+ # # sleep 120
673
+ # sub.detached? #=> true
674
+ #
675
+ def detach
676
+ ensure_service!
677
+ service.detach_subscription name
678
+ true
679
+ end
680
+
422
681
  ##
423
682
  # Pulls messages from the server. Returns an empty list if there are no
424
683
  # messages available in the backlog. Raises an ApiError with status
@@ -556,8 +815,20 @@ module Google
556
815
  # argument is not provided. See {#reference?}.
557
816
  # @param [Integer] streams The number of concurrent streams to open to
558
817
  # pull messages from the subscription. Default is 4. Optional.
559
- # @param [Integer] inventory The number of received messages to be
560
- # collected by subscriber. Default is 1,000. Optional.
818
+ # @param [Hash, Integer] inventory The settings to control how received messages are to be handled by the
819
+ # subscriber. When provided as an Integer instead of a Hash only the `limit` will be set. Optional.
820
+ #
821
+ # Hash keys and values may include the following:
822
+ #
823
+ # * `:max_outstanding_messages` [Integer] The number of received messages to be collected by subscriber.
824
+ # Default is 1,000. (Note: replaces `:limit`, which is deprecated.)
825
+ # * `:max_outstanding_bytes` [Integer] The total byte size of received messages to be collected by
826
+ # subscriber. Default is 100,000,000 (100MB). (Note: replaces `:bytesize`, which is deprecated.)
827
+ # * `:max_total_lease_duration` [Integer] The number of seconds that received messages can be held awaiting
828
+ # processing. Default is 3,600 (1 hour). (Note: replaces `:extension`, which is deprecated.)
829
+ # * `:max_duration_per_lease_extension` [Integer] The maximum amount of time in seconds for a single lease
830
+ # extension attempt. Bounds the delay before a message redelivery if the subscriber fails to extend the
831
+ # deadline. Default is 0 (disabled).
561
832
  # @param [Hash] threads The number of threads to create to handle
562
833
  # concurrent calls by each stream opened by the subscriber. Optional.
563
834
  #
@@ -633,6 +904,25 @@ module Google
633
904
  # # Shut down the subscriber when ready to stop receiving messages.
634
905
  # subscriber.stop.wait!
635
906
  #
907
+ # @example Set the maximum amount of time before redelivery if the subscriber fails to extend the deadline:
908
+ # require "google/cloud/pubsub"
909
+ #
910
+ # pubsub = Google::Cloud::PubSub.new
911
+ #
912
+ # sub = pubsub.subscription "my-topic-sub"
913
+ #
914
+ # subscriber = sub.listen inventory: { max_duration_per_lease_extension: 20 } do |received_message|
915
+ # # Process message very slowly with possibility of failure.
916
+ # process rec_message.data # takes minutes
917
+ # rec_message.acknowledge!
918
+ # end
919
+ #
920
+ # # Start background threads that will call block passed to listen.
921
+ # subscriber.start
922
+ #
923
+ # # Shut down the subscriber when ready to stop receiving messages.
924
+ # subscriber.stop.wait!
925
+ #
636
926
  def listen deadline: nil, message_ordering: nil, streams: nil, inventory: nil, threads: {}, &block
637
927
  ensure_service!
638
928
  deadline ||= self.deadline