google-cloud-pubsub 1.1.3 → 1.10.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 (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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1feb85392aa3adbb0358718fbd2b3f9cfad766c2dd30fa03ffdd93a0ab9199f3
4
- data.tar.gz: 726f51f0d1851d82de1ee42230da2480a39d1dc18e3ebe418afdb03ce28fa6ea
3
+ metadata.gz: 43ee60087a74bfc9938a61cf66f67b937f30c440f921ef83294f5dd2ec8e1079
4
+ data.tar.gz: 9104bacc161434e7edc1b5553cb0d2f2681ddd6a6a000bf947e212af7dad4df0
5
5
  SHA512:
6
- metadata.gz: 9c9b2ac59f9fac674bb1bfbddf8d5a23cf768986fbd13e0e41128bf86574884b3d46cd88c564f9b28a531dfebaf6ba05bced34d5f6ee50664442876eea601d6a
7
- data.tar.gz: e3e93f611b142aad3e8323d3aeae2339c810924f31369370e668063da54af64806b0270db81c75b2e6361537ec596d238a5bad4c8cdf79a4d818af08790efc6b
6
+ metadata.gz: 4130c4d2961f54b8cf6f1a5957f50d50e37d57bcd56d032df3bbc10497e8788d55e405c69b8570cc24322800af37a35e49daf67755b1652b763b5a9da44b464e
7
+ data.tar.gz: 5777e0c8d1ca9d56c2a94056971b1e59ccf63e3a1e6dd532f5d223f7a6b8a80f0f0aa29bf1aa984376b48d279bccc3e23aa4ff50940c47b4920c47a6340e5975
data/CHANGELOG.md CHANGED
@@ -1,5 +1,127 @@
1
1
  # Release History
2
2
 
3
+ ### 1.10.0 / 2020-07-23
4
+
5
+ #### Features
6
+
7
+ * Add Subscription#detach and #detached?
8
+
9
+ ### 1.9.0 / 2020-07-21
10
+
11
+ #### Features
12
+
13
+ * Add support for server-side flow control
14
+
15
+ ### 1.8.0 / 2020-06-29
16
+
17
+ #### Features
18
+
19
+ * Add Subscription#filter
20
+
21
+ ### 1.7.1 / 2020-05-28
22
+
23
+ #### Documentation
24
+
25
+ * Fix a few broken links
26
+
27
+ ### 1.7.0 / 2020-05-21
28
+
29
+ #### Features
30
+
31
+ * Add Retry Policy support
32
+ * Add RetryPolicy
33
+ * Add retry_policy param to Topic#subscribe
34
+ * Add Subscription#retry_policy
35
+ * Add Subscription#retry_policy=
36
+ * Set client-scoped UUID in initial StreamingPullRequest#client_id
37
+
38
+ ### 1.6.1 / 2020-05-06
39
+
40
+ #### Documentation
41
+
42
+ * Fix example in Emulator documentation
43
+ * Remove experimental notice from ReceivedMessage#delivery_attempt
44
+ * Wrap example URLs in backticks
45
+
46
+ ### 1.6.0 / 2020-04-06
47
+
48
+ #### Features
49
+
50
+ * Add list_topic_snapshots and get_snapshot
51
+ * Add PublisherClient#list_topic_snapshots
52
+ * Add SubscriberClient#get_snapshot
53
+
54
+ #### Documentation
55
+
56
+ * Remove a spurious link in the low-level interface documentation.
57
+
58
+ ### 1.5.0 / 2020-03-25
59
+
60
+ #### Features
61
+
62
+ * Add max_duration_per_lease_extension to Subscription#listen and Subscriber
63
+
64
+ ### 1.4.0 / 2020-03-11
65
+
66
+ #### Features
67
+
68
+ * Rename Subscriber inventory methods and params
69
+ * Rename Subscriber#inventory_limit to #max_outstanding_messages
70
+ * Rename Subscriber#bytesize to #max_outstanding_bytes
71
+ * Rename Subscriber#extension to #max_total_lease_duration
72
+ * Add deprecated aliases for the original methods
73
+ * Support separate project setting for quota/billing
74
+
75
+ #### Documentation
76
+
77
+ * Update documentation in the lower-level client
78
+
79
+ ### 1.3.1 / 2020-02-18
80
+
81
+ #### Bug Fixes
82
+
83
+ * Move Thread.new to end of AsyncPublisher#initialize
84
+
85
+ ### 1.3.0 / 2020-02-10
86
+
87
+ #### Features
88
+
89
+ * Add support for Dead Letter Topics
90
+ * Add `dead_letter_topic` and `dead_letter_max_delivery_attempts` to `Topic#subscribe`
91
+ * Add `Subscription#dead_letter_topic` and `Subscription#dead_letter_topic=`
92
+ * Add `Subscription#dead_letter_max_delivery_attempts` and `Subscription#dead_letter_max_delivery_attempts=`
93
+ * Add `ReceivedMessage#delivery_attempt`
94
+
95
+ ### 1.2.2 / 2020-02-04
96
+
97
+ #### Performance Improvements
98
+
99
+ * Add StreamingPullRequest#client_id to the lower-level API
100
+
101
+ ### 1.2.1 / 2020-01-23
102
+
103
+ #### Documentation
104
+
105
+ * Update copyright year
106
+
107
+ ### 1.2.0 / 2020-01-09
108
+
109
+ #### Features
110
+
111
+ * Add Subscriber inventory settings
112
+ * Add the following settings to Subscriber:
113
+ * Subscriber#inventory_limit
114
+ * Subscriber#inventory_bytesize
115
+ * Subscriber#extension
116
+ * Allow Subscription#listen inventory argument to be a hash.
117
+ * Update AsyncPublisher configuration defaults
118
+ * Update AsyncPublisher defaults to the following:
119
+ * max_bytes to 1MB, was 10MB.
120
+ * max_messages to 100, was 1,000.
121
+ * interval to 10 milliseconds, was 250 milliseconds.
122
+ * publish thread count to 2, was 4
123
+ * callback thread count to 4, was 8.
124
+
3
125
  ### 1.1.3 / 2019-12-18
4
126
 
5
127
  #### Bug Fixes
data/EMULATOR.md CHANGED
@@ -17,7 +17,7 @@ require "google/cloud/pubsub"
17
17
  # Make Pub/Sub use the emulator
18
18
  ENV["PUBSUB_EMULATOR_HOST"] = "localhost:8918"
19
19
 
20
- pubsub = Google::Cloud::PubSub.new "emulator-project-id"
20
+ pubsub = Google::Cloud::PubSub.new project_id:"emulator-project-id"
21
21
 
22
22
  # Get a topic in the current project
23
23
  my_topic = pubsub.new_topic "my-topic"
data/TROUBLESHOOTING.md CHANGED
@@ -24,14 +24,8 @@ improved, *please* create a new issue on GitHub so we can talk about it.
24
24
 
25
25
  - [New issue][gh-ruby]
26
26
 
27
- Or, you can ask questions on the [Google Cloud Platform Slack][slack-ruby]. You
28
- can use the "ruby" channel for general Ruby questions, or use the
29
- "google-cloud-ruby" channel if you have questions about this gem in particular.
30
-
31
27
  [so-ruby]: http://stackoverflow.com/questions/tagged/google-cloud-platform+ruby+pubsub
32
28
 
33
- [gh-search-ruby]: https://github.com/googlecloudplatform/google-cloud-ruby/issues?q=label%3A%22api%3A+pubsub%22
34
-
35
- [gh-ruby]: https://github.com/googlecloudplatform/google-cloud-ruby/issues/new
29
+ [gh-search-ruby]: https://github.com/googleapis/google-cloud-ruby/issues?q=label%3A%22api%3A+pubsub%22
36
30
 
37
- [slack-ruby]: https://gcp-slack.appspot.com/
31
+ [gh-ruby]: https://github.com/googleapis/google-cloud-ruby/issues/new
@@ -44,20 +44,17 @@ module Google
44
44
  #
45
45
  # topic.async_publisher.stop.wait!
46
46
  #
47
- # @attr_reader [String] topic_name The name of the topic the messages
48
- # are published to. In the form of
47
+ # @attr_reader [String] topic_name The name of the topic the messages are published to. In the form of
49
48
  # "/projects/project-identifier/topics/topic-name".
50
- # @attr_reader [Integer] max_bytes The maximum size of messages to be
51
- # collected before the batch is published. Default is 10,000,000
52
- # (10MB).
53
- # @attr_reader [Integer] max_messages The maximum number of messages to
54
- # be collected before the batch is published. Default is 1,000.
55
- # @attr_reader [Numeric] interval The number of seconds to collect
56
- # messages before the batch is published. Default is 0.25.
57
- # @attr_reader [Numeric] publish_threads The number of threads used to
58
- # publish messages. Default is 4.
59
- # @attr_reader [Numeric] callback_threads The number of threads to
60
- # handle the published messages' callbacks. Default is 8.
49
+ # @attr_reader [Integer] max_bytes The maximum size of messages to be collected before the batch is published.
50
+ # Default is 1,000,000 (1MB).
51
+ # @attr_reader [Integer] max_messages The maximum number of messages to be collected before the batch is
52
+ # published. Default is 100.
53
+ # @attr_reader [Numeric] interval The number of seconds to collect messages before the batch is published. Default
54
+ # is 0.01.
55
+ # @attr_reader [Numeric] publish_threads The number of threads used to publish messages. Default is 2.
56
+ # @attr_reader [Numeric] callback_threads The number of threads to handle the published messages' callbacks.
57
+ # Default is 4.
61
58
  #
62
59
  class AsyncPublisher
63
60
  include MonitorMixin
@@ -71,28 +68,27 @@ module Google
71
68
 
72
69
  ##
73
70
  # @private Create a new instance of the object.
74
- def initialize topic_name, service, max_bytes: 10_000_000, max_messages: 1000, interval: 0.25, threads: {}
71
+ def initialize topic_name, service, max_bytes: 1_000_000, max_messages: 100, interval: 0.01, threads: {}
75
72
  # init MonitorMixin
76
73
  super()
77
-
78
74
  @topic_name = service.topic_path topic_name
79
75
  @service = service
80
76
 
81
77
  @max_bytes = max_bytes
82
78
  @max_messages = max_messages
83
79
  @interval = interval
84
- @publish_threads = (threads[:publish] || 4).to_i
85
- @callback_threads = (threads[:callback] || 8).to_i
80
+ @publish_threads = (threads[:publish] || 2).to_i
81
+ @callback_threads = (threads[:callback] || 4).to_i
86
82
 
87
83
  @published_at = nil
88
84
  @publish_thread_pool = Concurrent::ThreadPoolExecutor.new max_threads: @publish_threads
89
85
  @callback_thread_pool = Concurrent::ThreadPoolExecutor.new max_threads: @callback_threads
90
- @thread = Thread.new { run_background }
91
86
 
92
87
  @ordered = false
93
88
  @batches = {}
94
-
95
89
  @cond = new_cond
90
+
91
+ @thread = Thread.new { run_background }
96
92
  end
97
93
 
98
94
  ##
@@ -89,19 +89,15 @@ module Google
89
89
  #
90
90
  # Hash keys and values may include the following:
91
91
  #
92
- # * `:max_bytes` (Integer) The maximum size of messages to be
93
- # collected before the batch is published. Default is 10,000,000
94
- # (10MB).
95
- # * `:max_messages` (Integer) The maximum number of messages to be
96
- # collected before the batch is published. Default is 1,000.
97
- # * `:interval` (Numeric) The number of seconds to collect messages
98
- # before the batch is published. Default is 0.25.
99
- # * `:threads` (Hash) The number of threads to create to handle
100
- # concurrent calls by the publisher:
101
- # * `:publish` (Integer) The number of threads used to publish
102
- # messages. Default is 4.
103
- # * `:callback` (Integer) The number of threads to handle the
104
- # published messages' callbacks. Default is 8.
92
+ # * `:max_bytes` (Integer) The maximum size of messages to be collected before the batch is published. Default
93
+ # is 1,000,000 (1MB).
94
+ # * `:max_messages` (Integer) The maximum number of messages to be collected before the batch is published.
95
+ # Default is 100.
96
+ # * `:interval` (Numeric) The number of seconds to collect messages before the batch is published. Default is
97
+ # 0.01.
98
+ # * `:threads` (Hash) The number of threads to create to handle concurrent calls by the publisher:
99
+ # * `:publish` (Integer) The number of threads used to publish messages. Default is 2.
100
+ # * `:callback` (Integer) The number of threads to handle the published messages' callbacks. Default is 4.
105
101
  #
106
102
  # @return [Google::Cloud::PubSub::Topic, nil] Returns `nil` if topic
107
103
  # does not exist.
@@ -183,19 +179,15 @@ module Google
183
179
  #
184
180
  # Hash keys and values may include the following:
185
181
  #
186
- # * `:max_bytes` (Integer) The maximum size of messages to be
187
- # collected before the batch is published. Default is 10,000,000
188
- # (10MB).
189
- # * `:max_messages` (Integer) The maximum number of messages to be
190
- # collected before the batch is published. Default is 1,000.
191
- # * `:interval` (Numeric) The number of seconds to collect messages
192
- # before the batch is published. Default is 0.25.
193
- # * `:threads` (Hash) The number of threads to create to handle
194
- # concurrent calls by the publisher:
195
- # * `:publish` (Integer) The number of threads used to publish
196
- # messages. Default is 4.
197
- # * `:callback` (Integer) The number of threads to handle the
198
- # published messages' callbacks. Default is 8.
182
+ # * `:max_bytes` (Integer) The maximum size of messages to be collected before the batch is published. Default
183
+ # is 1,000,000 (1MB).
184
+ # * `:max_messages` (Integer) The maximum number of messages to be collected before the batch is published.
185
+ # Default is 100.
186
+ # * `:interval` (Numeric) The number of seconds to collect messages before the batch is published. Default is
187
+ # 0.01.
188
+ # * `:threads` (Hash) The number of threads to create to handle concurrent calls by the publisher:
189
+ # * `:publish` (Integer) The number of threads used to publish messages. Default is 2.
190
+ # * `:callback` (Integer) The number of threads to handle the published messages' callbacks. Default is 4.
199
191
  #
200
192
  # @return [Google::Cloud::PubSub::Topic]
201
193
  #
@@ -63,6 +63,44 @@ module Google
63
63
  @grpc.ack_id
64
64
  end
65
65
 
66
+ ##
67
+ # Returns the delivery attempt counter for the message. If a dead letter policy is not set on the subscription,
68
+ # this will be `nil`. See {Topic#subscribe}, {Subscription#dead_letter_topic=} and
69
+ # {Subscription#dead_letter_max_delivery_attempts=}.
70
+ #
71
+ # The delivery attempt counter is `1 + (the sum of number of NACKs and number of ack_deadline exceeds)` for the
72
+ # message.
73
+ #
74
+ # A NACK is any call to `ModifyAckDeadline` with a `0` deadline. An `ack_deadline` exceeds event is whenever a
75
+ # message is not acknowledged within `ack_deadline`. Note that `ack_deadline` is initially
76
+ # `Subscription.ackDeadlineSeconds`, but may get extended automatically by the client library.
77
+ #
78
+ # The first delivery of a given message will have this value as `1`. The value is calculated at best effort and
79
+ # is approximate.
80
+ #
81
+ # @return [Integer, nil] A delivery attempt value of `1` or greater, or `nil` if a dead letter policy is not set
82
+ # on the subscription.
83
+ #
84
+ # @example
85
+ # require "google/cloud/pubsub"
86
+ #
87
+ # pubsub = Google::Cloud::PubSub.new
88
+ #
89
+ # topic = pubsub.topic "my-topic"
90
+ # dead_letter_topic = pubsub.topic "my-dead-letter-topic", skip_lookup: true
91
+ # sub = topic.subscribe "my-topic-sub",
92
+ # dead_letter_topic: dead_letter_topic,
93
+ # dead_letter_max_delivery_attempts: 10
94
+ #
95
+ # subscriber = sub.listen do |received_message|
96
+ # puts received_message.message.delivery_attempt
97
+ # end
98
+ #
99
+ def delivery_attempt
100
+ return nil if @grpc.delivery_attempt && @grpc.delivery_attempt < 1
101
+ @grpc.delivery_attempt
102
+ end
103
+
66
104
  ##
67
105
  # The received message.
68
106
  def message
@@ -0,0 +1,90 @@
1
+ # Copyright 2016 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/cloud/errors"
17
+
18
+ module Google
19
+ module Cloud
20
+ module PubSub
21
+ ##
22
+ # # RetryPolicy
23
+ #
24
+ # An immutable Retry Policy value object that specifies how Cloud Pub/Sub retries message delivery.
25
+ #
26
+ # Retry delay will be exponential based on provided minimum and maximum backoffs. (See [Exponential
27
+ # backoff](https://en.wikipedia.org/wiki/Exponential_backoff).)
28
+ #
29
+ # Retry Policy will be triggered on NACKs or acknowledgement deadline exceeded events for a given message.
30
+ #
31
+ # Retry Policy is implemented on a best effort basis. At times, the delay between consecutive deliveries may not
32
+ # match the configuration. That is, delay can be more or less than configured backoff.
33
+ #
34
+ # **EXPERIMENTAL:** This API might be changed in backward-incompatible ways and is not recommended for production
35
+ # use. It is not subject to any SLA or deprecation policy.
36
+ #
37
+ # @attr [Numeric] minimum_backoff The minimum delay between consecutive deliveries of a given message. Value
38
+ # should be between 0 and 600 seconds. The default value is 10 seconds.
39
+ # @attr [Numeric] maximum_backoff The maximum delay between consecutive deliveries of a given message. Value
40
+ # should be between 0 and 600 seconds. The default value is 600 seconds.
41
+ #
42
+ # @example
43
+ # require "google/cloud/pubsub"
44
+ #
45
+ # pubsub = Google::Cloud::PubSub.new
46
+ #
47
+ # sub = pubsub.subscription "my-topic-sub"
48
+ #
49
+ # sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
50
+ #
51
+ # sub.retry_policy.minimum_backoff #=> 5
52
+ # sub.retry_policy.maximum_backoff #=> 300
53
+ #
54
+ class RetryPolicy
55
+ attr_reader :minimum_backoff, :maximum_backoff
56
+
57
+ ##
58
+ # Creates a new, immutable RetryPolicy value object.
59
+ #
60
+ # @attr [Numeric, nil] minimum_backoff The minimum delay between consecutive deliveries of a given message.
61
+ # Value should be between 0 and 600 seconds. If `nil` is provided, the default value is 10 seconds.
62
+ # @attr [Numeric, nil] maximum_backoff The maximum delay between consecutive deliveries of a given message.
63
+ # Value should be between 0 and 600 seconds. If `nil` is provided, the default value is 600 seconds.
64
+ #
65
+ def initialize minimum_backoff: nil, maximum_backoff: nil
66
+ @minimum_backoff = minimum_backoff
67
+ @maximum_backoff = maximum_backoff
68
+ end
69
+
70
+ ##
71
+ # @private Convert the RetryPolicy to a Google::Cloud::PubSub::V1::RetryPolicy object.
72
+ def to_grpc
73
+ Google::Cloud::PubSub::V1::RetryPolicy.new(
74
+ minimum_backoff: Convert.number_to_duration(minimum_backoff),
75
+ maximum_backoff: Convert.number_to_duration(maximum_backoff)
76
+ )
77
+ end
78
+
79
+ ##
80
+ # @private New RetryPolicy from a Google::Cloud::PubSub::V1::RetryPolicy object.
81
+ def self.from_grpc grpc
82
+ new(
83
+ minimum_backoff: Convert.duration_to_number(grpc.minimum_backoff),
84
+ maximum_backoff: Convert.duration_to_number(grpc.maximum_backoff)
85
+ )
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -19,6 +19,7 @@ require "google/cloud/pubsub/convert"
19
19
  require "google/cloud/pubsub/version"
20
20
  require "google/cloud/pubsub/v1"
21
21
  require "google/gax/errors"
22
+ require "securerandom"
22
23
 
23
24
  module Google
24
25
  module Cloud
@@ -28,6 +29,12 @@ module Google
28
29
  # methods.
29
30
  class Service
30
31
  attr_accessor :project, :credentials, :host, :timeout, :client_config
32
+ ###
33
+ # The same client_id is used across all streaming pull connections that are created by this client. This is
34
+ # intentional, as it indicates to the server that any guarantees, such as message ordering, made for a stream
35
+ # that is disconnected will be made for the stream that is created to replace it. The attr_accessor allows the
36
+ # value to be replaced for unit testing.
37
+ attr_accessor :client_id
31
38
 
32
39
  ##
33
40
  # Creates a new Service instance.
@@ -38,6 +45,7 @@ module Google
38
45
  @host = host || V1::PublisherClient::SERVICE_ADDRESS
39
46
  @timeout = timeout
40
47
  @client_config = client_config || {}
48
+ @client_id = SecureRandom.uuid.freeze
41
49
  end
42
50
 
43
51
  def channel
@@ -233,21 +241,18 @@ module Google
233
241
  push_endpoint: options[:endpoint],
234
242
  attributes: (options[:attributes] || {}).to_h
235
243
  end
236
- deadline = options[:deadline]
237
- retain_acked = options[:retain_acked]
238
- mrd = Convert.number_to_duration options[:retention]
239
- labels = options[:labels]
240
- message_ordering = options[:message_ordering]
241
-
242
244
  execute do
243
245
  subscriber.create_subscription \
244
246
  name, topic,
245
247
  push_config: push_config,
246
- ack_deadline_seconds: deadline,
247
- retain_acked_messages: retain_acked,
248
- message_retention_duration: mrd,
249
- labels: labels,
250
- enable_message_ordering: message_ordering,
248
+ ack_deadline_seconds: options[:deadline],
249
+ retain_acked_messages: options[:retain_acked],
250
+ message_retention_duration: Convert.number_to_duration(options[:retention]),
251
+ labels: options[:labels],
252
+ enable_message_ordering: options[:message_ordering],
253
+ filter: options[:filter],
254
+ dead_letter_policy: dead_letter_policy(options),
255
+ retry_policy: options[:retry_policy],
251
256
  options: default_options
252
257
  end
253
258
  end
@@ -260,12 +265,20 @@ module Google
260
265
  end
261
266
 
262
267
  ##
263
- # Deletes an existing subscription.
264
- # All pending messages in the subscription are immediately dropped.
268
+ # Deletes an existing subscription. All pending messages in the subscription are immediately dropped.
265
269
  def delete_subscription subscription
266
270
  execute do
267
- subscriber.delete_subscription subscription_path(subscription),
268
- options: default_options
271
+ subscriber.delete_subscription subscription_path(subscription), options: default_options
272
+ end
273
+ end
274
+
275
+ ##
276
+ # Detaches a subscription from its topic. All messages retained in the subscription are dropped. Subsequent
277
+ # `Pull` and `StreamingPull` requests will raise `FAILED_PRECONDITION`. If the subscription is a push
278
+ # subscription, pushes to the endpoint will stop.
279
+ def detach_subscription subscription
280
+ execute do
281
+ publisher.detach_subscription subscription_path(subscription), options: default_options
269
282
  end
270
283
  end
271
284
 
@@ -477,6 +490,15 @@ module Google
477
490
  true
478
491
  end
479
492
 
493
+ def dead_letter_policy options
494
+ return nil unless options[:dead_letter_topic_name]
495
+ policy = Google::Cloud::PubSub::V1::DeadLetterPolicy.new dead_letter_topic: options[:dead_letter_topic_name]
496
+ if options[:dead_letter_max_delivery_attempts]
497
+ policy.max_delivery_attempts = options[:dead_letter_max_delivery_attempts]
498
+ end
499
+ policy
500
+ end
501
+
480
502
  def default_headers
481
503
  { "google-cloud-resource-prefix" => "projects/#{@project}" }
482
504
  end
@@ -22,30 +22,40 @@ module Google
22
22
  ##
23
23
  # @private
24
24
  class Inventory
25
+ InventoryItem = Struct.new :bytesize, :pulled_at do
26
+ def self.from rec_msg
27
+ new rec_msg.to_proto.bytesize, Time.now
28
+ end
29
+ end
30
+
25
31
  include MonitorMixin
26
32
 
27
- attr_reader :stream, :limit
33
+ attr_reader :stream, :limit, :bytesize, :extension, :max_duration_per_lease_extension
28
34
 
29
- def initialize stream, limit
35
+ def initialize stream, limit:, bytesize:, extension:, max_duration_per_lease_extension:
30
36
  super()
31
-
32
37
  @stream = stream
33
38
  @limit = limit
34
- @_ack_ids = []
39
+ @bytesize = bytesize
40
+ @extension = extension
41
+ @max_duration_per_lease_extension = max_duration_per_lease_extension
42
+ @inventory = {}
35
43
  @wait_cond = new_cond
36
44
  end
37
45
 
38
46
  def ack_ids
39
- @_ack_ids
47
+ @inventory.keys
40
48
  end
41
49
 
42
- def add *ack_ids
43
- ack_ids.flatten!
44
- ack_ids.compact!
45
- return if ack_ids.empty?
50
+ def add *rec_msgs
51
+ rec_msgs.flatten!
52
+ rec_msgs.compact!
53
+ return if rec_msgs.empty?
46
54
 
47
55
  synchronize do
48
- @_ack_ids += ack_ids
56
+ rec_msgs.each do |rec_msg|
57
+ @inventory[rec_msg.ack_id] = InventoryItem.from rec_msg
58
+ end
49
59
  @wait_cond.broadcast
50
60
  end
51
61
  end
@@ -56,20 +66,34 @@ module Google
56
66
  return if ack_ids.empty?
57
67
 
58
68
  synchronize do
59
- @_ack_ids -= ack_ids
69
+ @inventory.delete_if { |ack_id, _| ack_ids.include? ack_id }
70
+ @wait_cond.broadcast
71
+ end
72
+ end
73
+
74
+ def remove_expired!
75
+ synchronize do
76
+ extension_time = Time.new - extension
77
+ @inventory.delete_if { |_ack_id, item| item.pulled_at < extension_time }
60
78
  @wait_cond.broadcast
61
79
  end
62
80
  end
63
81
 
64
82
  def count
65
83
  synchronize do
66
- @_ack_ids.count
84
+ @inventory.count
85
+ end
86
+ end
87
+
88
+ def total_bytesize
89
+ synchronize do
90
+ @inventory.values.sum(&:bytesize)
67
91
  end
68
92
  end
69
93
 
70
94
  def empty?
71
95
  synchronize do
72
- @_ack_ids.empty?
96
+ @inventory.empty?
73
97
  end
74
98
  end
75
99
 
@@ -93,7 +117,9 @@ module Google
93
117
  end
94
118
 
95
119
  def full?
96
- count >= limit
120
+ synchronize do
121
+ @inventory.count >= limit || @inventory.values.sum(&:bytesize) >= bytesize
122
+ end
97
123
  end
98
124
 
99
125
  protected
@@ -127,7 +153,9 @@ module Google
127
153
  end
128
154
 
129
155
  def calc_delay
130
- (stream.subscriber.deadline - 3) * rand(0.8..0.9)
156
+ delay = (stream.subscriber.deadline - 3) * rand(0.8..0.9)
157
+ delay = [delay, max_duration_per_lease_extension].min if max_duration_per_lease_extension.positive?
158
+ delay
131
159
  end
132
160
  end
133
161
  end