google-cloud-pubsub 1.1.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +2 -1
  3. data/CHANGELOG.md +145 -0
  4. data/EMULATOR.md +1 -1
  5. data/TROUBLESHOOTING.md +2 -8
  6. data/lib/google/cloud/pubsub/async_publisher.rb +16 -21
  7. data/lib/google/cloud/pubsub/credentials.rb +2 -2
  8. data/lib/google/cloud/pubsub/project.rb +18 -26
  9. data/lib/google/cloud/pubsub/received_message.rb +38 -0
  10. data/lib/google/cloud/pubsub/retry_policy.rb +90 -0
  11. data/lib/google/cloud/pubsub/service.rb +125 -252
  12. data/lib/google/cloud/pubsub/subscriber/inventory.rb +43 -15
  13. data/lib/google/cloud/pubsub/subscriber/stream.rb +8 -10
  14. data/lib/google/cloud/pubsub/subscriber.rb +86 -15
  15. data/lib/google/cloud/pubsub/subscription/push_config.rb +2 -2
  16. data/lib/google/cloud/pubsub/subscription.rb +297 -7
  17. data/lib/google/cloud/pubsub/topic.rb +65 -2
  18. data/lib/google/cloud/pubsub/version.rb +1 -1
  19. data/lib/google/cloud/pubsub.rb +15 -18
  20. data/lib/google-cloud-pubsub.rb +13 -13
  21. metadata +11 -81
  22. data/lib/google/cloud/pubsub/v1/credentials.rb +0 -41
  23. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/iam_policy.rb +0 -21
  24. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/options.rb +0 -21
  25. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/policy.rb +0 -21
  26. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +0 -91
  27. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/empty.rb +0 -29
  28. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +0 -222
  29. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +0 -113
  30. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +0 -744
  31. data/lib/google/cloud/pubsub/v1/doc/google/type/expr.rb +0 -19
  32. data/lib/google/cloud/pubsub/v1/publisher_client.rb +0 -786
  33. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +0 -105
  34. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +0 -1385
  35. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +0 -144
  36. data/lib/google/cloud/pubsub/v1.rb +0 -17
  37. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -249
  38. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -211
@@ -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|
@@ -275,9 +271,8 @@ module Google
275
271
  stop
276
272
  rescue GRPC::Cancelled, GRPC::DeadlineExceeded, GRPC::Internal,
277
273
  GRPC::ResourceExhausted, GRPC::Unauthenticated,
278
- GRPC::Unavailable, GRPC::Core::CallError
274
+ GRPC::Unavailable
279
275
  # Restart the stream with an incremental back for a retriable error.
280
- # Also when GRPC raises the internal CallError.
281
276
 
282
277
  retry
283
278
  rescue RestartStream
@@ -367,6 +362,9 @@ module Google
367
362
  req.stream_ack_deadline_seconds = @subscriber.deadline
368
363
  req.modify_deadline_ack_ids += @inventory.ack_ids
369
364
  req.modify_deadline_seconds += @inventory.ack_ids.map { @subscriber.deadline }
365
+ req.client_id = @subscriber.service.client_id
366
+ req.max_outstanding_messages = @inventory.limit
367
+ req.max_outstanding_bytes = @inventory.bytesize
370
368
  end
371
369
  end
372
370
 
@@ -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.
@@ -344,13 +346,215 @@ module Google
344
346
  # to unset.
345
347
  #
346
348
  def expires_in= ttl
347
- new_expiration_policy = Google::Pubsub::V1::ExpirationPolicy.new ttl: Convert.number_to_duration(ttl)
349
+ new_expiration_policy = Google::Cloud::PubSub::V1::ExpirationPolicy.new ttl: Convert.number_to_duration(ttl)
348
350
 
349
351
  update_grpc = Google::Cloud::PubSub::V1::Subscription.new name: name, expiration_policy: new_expiration_policy
350
352
  @grpc = service.update_subscription update_grpc, :expiration_policy
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