google-cloud-pubsub 0.26.0 → 2.6.1

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 (56) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +12 -2
  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 +2 -2
  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 +80 -17
  19. data/lib/google/cloud/pubsub/policy.rb +17 -14
  20. data/lib/google/cloud/pubsub/project.rb +364 -250
  21. data/lib/google/cloud/pubsub/publish_result.rb +103 -0
  22. data/lib/google/cloud/pubsub/received_message.rb +162 -24
  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 +281 -265
  27. data/lib/google/cloud/pubsub/snapshot/list.rb +21 -21
  28. data/lib/google/cloud/pubsub/snapshot.rb +55 -15
  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 +28 -28
  36. data/lib/google/cloud/pubsub/subscription/push_config.rb +268 -0
  37. data/lib/google/cloud/pubsub/subscription.rb +900 -172
  38. data/lib/google/cloud/pubsub/topic/list.rb +21 -21
  39. data/lib/google/cloud/pubsub/topic.rb +674 -95
  40. data/lib/google/cloud/pubsub/version.rb +6 -4
  41. data/lib/google/cloud/pubsub.rb +104 -439
  42. data/lib/google-cloud-pubsub.rb +60 -29
  43. metadata +88 -50
  44. data/README.md +0 -69
  45. data/lib/google/cloud/pubsub/topic/publisher.rb +0 -86
  46. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +0 -77
  47. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +0 -223
  48. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +0 -81
  49. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +0 -503
  50. data/lib/google/cloud/pubsub/v1/publisher_client.rb +0 -605
  51. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +0 -96
  52. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +0 -1104
  53. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +0 -127
  54. data/lib/google/cloud/pubsub/v1.rb +0 -17
  55. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -187
  56. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -159
@@ -0,0 +1,230 @@
1
+ # Copyright 2018 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 "concurrent"
17
+ require "monitor"
18
+
19
+ module Google
20
+ module Cloud
21
+ module PubSub
22
+ class Subscriber
23
+ ##
24
+ # @private
25
+ class TimedUnaryBuffer
26
+ include MonitorMixin
27
+
28
+ attr_reader :max_bytes
29
+ attr_reader :interval
30
+
31
+ def initialize subscriber, max_bytes: 500_000, interval: 1.0
32
+ super() # to init MonitorMixin
33
+
34
+ @subscriber = subscriber
35
+ @max_bytes = max_bytes
36
+ @interval = interval
37
+
38
+ # Using a Hash ensures there is only one entry for each ack_id in
39
+ # the buffer. Adding an entry again will overwrite the previous
40
+ # entry.
41
+ @register = {}
42
+
43
+ @task = Concurrent::TimerTask.new execution_interval: interval do
44
+ flush!
45
+ end
46
+ end
47
+
48
+ def acknowledge ack_ids
49
+ return if ack_ids.empty?
50
+
51
+ synchronize do
52
+ ack_ids.each do |ack_id|
53
+ # ack has no deadline set, use :ack indicate it is an ack
54
+ @register[ack_id] = :ack
55
+ end
56
+ end
57
+
58
+ true
59
+ end
60
+
61
+ def modify_ack_deadline deadline, ack_ids
62
+ return if ack_ids.empty?
63
+
64
+ synchronize do
65
+ ack_ids.each do |ack_id|
66
+ @register[ack_id] = deadline
67
+ end
68
+ end
69
+
70
+ true
71
+ end
72
+
73
+ def renew_lease deadline, ack_ids
74
+ return if ack_ids.empty?
75
+
76
+ synchronize do
77
+ ack_ids.each do |ack_id|
78
+ # Don't overwrite pending actions when renewing leased messages.
79
+ @register[ack_id] ||= deadline
80
+ end
81
+ end
82
+
83
+ true
84
+ end
85
+
86
+ def flush!
87
+ # Grab requests from the buffer and release synchronize ASAP
88
+ requests = flush_requests!
89
+ return if requests.empty?
90
+
91
+ # Perform the RCP calls concurrently
92
+ with_threadpool do |pool|
93
+ requests[:acknowledge].each do |ack_req|
94
+ add_future pool do
95
+ @subscriber.service.acknowledge ack_req.subscription, *ack_req.ack_ids
96
+ end
97
+ end
98
+ requests[:modify_ack_deadline].each do |mod_ack_req|
99
+ add_future pool do
100
+ @subscriber.service.modify_ack_deadline mod_ack_req.subscription, mod_ack_req.ack_ids,
101
+ mod_ack_req.ack_deadline_seconds
102
+ end
103
+ end
104
+ end
105
+
106
+ true
107
+ end
108
+
109
+ def start
110
+ @task.execute
111
+
112
+ self
113
+ end
114
+
115
+ def stop
116
+ @task.shutdown
117
+ flush!
118
+
119
+ self
120
+ end
121
+
122
+ def started?
123
+ @task.running?
124
+ end
125
+
126
+ def stopped?
127
+ !started?
128
+ end
129
+
130
+ private
131
+
132
+ def flush_requests!
133
+ prev_reg =
134
+ synchronize do
135
+ return {} if @register.empty?
136
+ reg = @register
137
+ @register = {}
138
+ reg
139
+ end
140
+
141
+ groups = prev_reg.each_pair.group_by { |_ack_id, delay| delay }
142
+ req_hash = groups.transform_values { |v| v.map(&:first) }
143
+
144
+ requests = { acknowledge: [] }
145
+ ack_ids = Array(req_hash.delete(:ack)) # ack has no deadline set
146
+ requests[:acknowledge] = create_acknowledge_requests ack_ids if ack_ids.any?
147
+ requests[:modify_ack_deadline] =
148
+ req_hash.map do |mod_deadline, mod_ack_ids|
149
+ create_modify_ack_deadline_requests mod_deadline, mod_ack_ids
150
+ end.flatten
151
+ requests
152
+ end
153
+
154
+ def create_acknowledge_requests ack_ids
155
+ req = Google::Cloud::PubSub::V1::AcknowledgeRequest.new(
156
+ subscription: subscription_name,
157
+ ack_ids: ack_ids
158
+ )
159
+ addl_to_create = req.to_proto.bytesize / max_bytes
160
+ return [req] if addl_to_create.zero?
161
+
162
+ ack_ids.each_slice(addl_to_create + 1).map do |sliced_ack_ids|
163
+ Google::Cloud::PubSub::V1::AcknowledgeRequest.new(
164
+ subscription: subscription_name,
165
+ ack_ids: sliced_ack_ids
166
+ )
167
+ end
168
+ end
169
+
170
+ def create_modify_ack_deadline_requests deadline, ack_ids
171
+ req = Google::Cloud::PubSub::V1::ModifyAckDeadlineRequest.new(
172
+ subscription: subscription_name,
173
+ ack_ids: ack_ids,
174
+ ack_deadline_seconds: deadline
175
+ )
176
+ addl_to_create = req.to_proto.bytesize / max_bytes
177
+ return [req] if addl_to_create.zero?
178
+
179
+ ack_ids.each_slice(addl_to_create + 1).map do |sliced_ack_ids|
180
+ Google::Cloud::PubSub::V1::ModifyAckDeadlineRequest.new(
181
+ subscription: subscription_name,
182
+ ack_ids: sliced_ack_ids,
183
+ ack_deadline_seconds: deadline
184
+ )
185
+ end
186
+ end
187
+
188
+ def subscription_name
189
+ @subscriber.subscription_name
190
+ end
191
+
192
+ def push_threads
193
+ @subscriber.push_threads
194
+ end
195
+
196
+ def error! error
197
+ @subscriber.error! error
198
+ end
199
+
200
+ def with_threadpool
201
+ pool = Concurrent::ThreadPoolExecutor.new max_threads: @subscriber.push_threads
202
+
203
+ yield pool
204
+
205
+ pool.shutdown
206
+ pool.wait_for_termination 60
207
+ return if pool.shutdown?
208
+
209
+ pool.kill
210
+ begin
211
+ raise "Timeout making subscriber API calls"
212
+ rescue StandardError => e
213
+ error! e
214
+ end
215
+ end
216
+
217
+ def add_future pool
218
+ Concurrent::Promises.future_on pool do
219
+ yield
220
+ rescue StandardError => e
221
+ error! e
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ Pubsub = PubSub unless const_defined? :Pubsub
229
+ end
230
+ end
@@ -0,0 +1,417 @@
1
+ # Copyright 2017 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/pubsub/service"
17
+ require "google/cloud/pubsub/subscriber/stream"
18
+ require "google/cloud/pubsub/subscriber/timed_unary_buffer"
19
+ require "monitor"
20
+
21
+ module Google
22
+ module Cloud
23
+ module PubSub
24
+ ##
25
+ # Subscriber object used to stream and process messages from a
26
+ # Subscription. See {Google::Cloud::PubSub::Subscription#listen}
27
+ #
28
+ # @example
29
+ # require "google/cloud/pubsub"
30
+ #
31
+ # pubsub = Google::Cloud::PubSub.new
32
+ #
33
+ # sub = pubsub.subscription "my-topic-sub"
34
+ #
35
+ # subscriber = sub.listen do |received_message|
36
+ # # process message
37
+ # received_message.acknowledge!
38
+ # end
39
+ #
40
+ # # Start background threads that will call the block passed to listen.
41
+ # subscriber.start
42
+ #
43
+ # # Shut down the subscriber when ready to stop receiving messages.
44
+ # subscriber.stop!
45
+ #
46
+ # @attr_reader [String] subscription_name The name of the subscription the
47
+ # messages are pulled from.
48
+ # @attr_reader [Proc] callback The procedure that will handle the messages
49
+ # received from the subscription.
50
+ # @attr_reader [Numeric] deadline The default number of seconds the stream
51
+ # will hold received messages before modifying the message's ack
52
+ # deadline. The minimum is 10, the maximum is 600. Default is 60.
53
+ # @attr_reader [Boolean] message_ordering Whether message ordering has
54
+ # been enabled.
55
+ # @attr_reader [Integer] streams The number of concurrent streams to open
56
+ # to pull messages from the subscription. Default is 4.
57
+ # @attr_reader [Integer] callback_threads The number of threads used to
58
+ # handle the received messages. Default is 8.
59
+ # @attr_reader [Integer] push_threads The number of threads to handle
60
+ # acknowledgement ({ReceivedMessage#ack!}) and delay messages
61
+ # ({ReceivedMessage#nack!}, {ReceivedMessage#modify_ack_deadline!}).
62
+ # Default is 4.
63
+ #
64
+ class Subscriber
65
+ include MonitorMixin
66
+
67
+ attr_reader :subscription_name
68
+ attr_reader :callback
69
+ attr_reader :deadline
70
+ attr_reader :streams
71
+ attr_reader :message_ordering
72
+ attr_reader :callback_threads
73
+ attr_reader :push_threads
74
+
75
+ ##
76
+ # @private Implementation attributes.
77
+ attr_reader :stream_pool, :thread_pool, :buffer, :service
78
+
79
+ ##
80
+ # @private Create an empty {Subscriber} object.
81
+ def initialize subscription_name, callback, deadline: nil, message_ordering: nil, streams: nil, inventory: nil,
82
+ threads: {}, service: nil
83
+ super() # to init MonitorMixin
84
+
85
+ @callback = callback
86
+ @error_callbacks = []
87
+ @subscription_name = subscription_name
88
+ @deadline = deadline || 60
89
+ @streams = streams || 2
90
+ coerce_inventory inventory
91
+ @message_ordering = message_ordering
92
+ @callback_threads = Integer(threads[:callback] || 8)
93
+ @push_threads = Integer(threads[:push] || 4)
94
+
95
+ @service = service
96
+
97
+ @started = @stopped = nil
98
+
99
+ stream_pool = Array.new @streams do
100
+ Thread.new { Stream.new self }
101
+ end
102
+ @stream_pool = stream_pool.map(&:value)
103
+
104
+ @buffer = TimedUnaryBuffer.new self
105
+ end
106
+
107
+ ##
108
+ # Starts the subscriber pulling from the subscription and processing the
109
+ # received messages.
110
+ #
111
+ # @return [Subscriber] returns self so calls can be chained.
112
+ #
113
+ def start
114
+ start_pool = synchronize do
115
+ @started = true
116
+ @stopped = false
117
+
118
+ # Start the buffer before the streams are all started
119
+ @buffer.start
120
+ @stream_pool.map do |stream|
121
+ Thread.new { stream.start }
122
+ end
123
+ end
124
+ start_pool.map(&:join)
125
+
126
+ self
127
+ end
128
+
129
+ ##
130
+ # Immediately stops the subscriber. No new messages will be pulled from
131
+ # the subscription. Use {#wait!} to block until all received messages have
132
+ # been processed or released: All actions taken on received messages that
133
+ # have not yet been sent to the API will be sent to the API. All received
134
+ # but unprocessed messages will be released back to the API and redelivered.
135
+ #
136
+ # @return [Subscriber] returns self so calls can be chained.
137
+ #
138
+ def stop
139
+ synchronize do
140
+ @started = false
141
+ @stopped = true
142
+ @stream_pool.map(&:stop)
143
+ wait_stop_buffer_thread!
144
+ self
145
+ end
146
+ end
147
+
148
+ ##
149
+ # Blocks until the subscriber is fully stopped and all received messages
150
+ # have been processed or released, or until `timeout` seconds have
151
+ # passed.
152
+ #
153
+ # Does not stop the subscriber. To stop the subscriber, first call
154
+ # {#stop} and then call {#wait!} to block until the subscriber is
155
+ # stopped.
156
+ #
157
+ # @param [Number, nil] timeout The number of seconds to block until the
158
+ # subscriber is fully stopped. Default will block indefinitely.
159
+ #
160
+ # @return [Subscriber] returns self so calls can be chained.
161
+ #
162
+ def wait! timeout = nil
163
+ wait_stop_buffer_thread!
164
+ @wait_stop_buffer_thread.join timeout
165
+ self
166
+ end
167
+
168
+ ##
169
+ # Stop this subscriber and block until the subscriber is fully stopped
170
+ # and all received messages have been processed or released, or until
171
+ # `timeout` seconds have passed.
172
+ #
173
+ # The same as calling {#stop} and {#wait!}.
174
+ #
175
+ # @param [Number, nil] timeout The number of seconds to block until the
176
+ # subscriber is fully stopped. Default will block indefinitely.
177
+ #
178
+ # @return [Subscriber] returns self so calls can be chained.
179
+ #
180
+ def stop! timeout = nil
181
+ stop
182
+ wait! timeout
183
+ end
184
+
185
+ ##
186
+ # Whether the subscriber has been started.
187
+ #
188
+ # @return [boolean] `true` when started, `false` otherwise.
189
+ #
190
+ def started?
191
+ synchronize { @started }
192
+ end
193
+
194
+ ##
195
+ # Whether the subscriber has been stopped.
196
+ #
197
+ # @return [boolean] `true` when stopped, `false` otherwise.
198
+ #
199
+ def stopped?
200
+ synchronize { @stopped }
201
+ end
202
+
203
+ ##
204
+ # Register to be notified of errors when raised.
205
+ #
206
+ # If an unhandled error has occurred the subscriber will attempt to
207
+ # recover from the error and resume listening.
208
+ #
209
+ # Multiple error handlers can be added.
210
+ #
211
+ # @yield [callback] The block to be called when an error is raised.
212
+ # @yieldparam [Exception] error The error raised.
213
+ #
214
+ # @example
215
+ # require "google/cloud/pubsub"
216
+ #
217
+ # pubsub = Google::Cloud::PubSub.new
218
+ #
219
+ # sub = pubsub.subscription "my-topic-sub"
220
+ #
221
+ # subscriber = sub.listen do |received_message|
222
+ # # process message
223
+ # received_message.acknowledge!
224
+ # end
225
+ #
226
+ # # Register to be notified when unhandled errors occur.
227
+ # subscriber.on_error do |error|
228
+ # # log error
229
+ # puts error
230
+ # end
231
+ #
232
+ # # Start listening for messages and errors.
233
+ # subscriber.start
234
+ #
235
+ # # Shut down the subscriber when ready to stop receiving messages.
236
+ # subscriber.stop!
237
+ #
238
+ def on_error &block
239
+ synchronize do
240
+ @error_callbacks << block
241
+ end
242
+ end
243
+
244
+ ##
245
+ # The most recent unhandled error to occur while listening to messages
246
+ # on the subscriber.
247
+ #
248
+ # If an unhandled error has occurred the subscriber will attempt to
249
+ # recover from the error and resume listening.
250
+ #
251
+ # @return [Exception, nil] error The most recent error raised.
252
+ #
253
+ # @example
254
+ # require "google/cloud/pubsub"
255
+ #
256
+ # pubsub = Google::Cloud::PubSub.new
257
+ #
258
+ # sub = pubsub.subscription "my-topic-sub"
259
+ #
260
+ # subscriber = sub.listen do |received_message|
261
+ # # process message
262
+ # received_message.acknowledge!
263
+ # end
264
+ #
265
+ # # Start listening for messages and errors.
266
+ # subscriber.start
267
+ #
268
+ # # If an error was raised, it can be retrieved here:
269
+ # subscriber.last_error #=> nil
270
+ #
271
+ # # Shut down the subscriber when ready to stop receiving messages.
272
+ # subscriber.stop!
273
+ #
274
+ def last_error
275
+ synchronize { @last_error }
276
+ end
277
+
278
+ ##
279
+ # The number of received messages to be collected by subscriber. Default is 1,000.
280
+ #
281
+ # @return [Integer] The maximum number of messages.
282
+ #
283
+ def max_outstanding_messages
284
+ @inventory[:max_outstanding_messages]
285
+ end
286
+ # @deprecated Use {#max_outstanding_messages}.
287
+ alias inventory_limit max_outstanding_messages
288
+ # @deprecated Use {#max_outstanding_messages}.
289
+ alias inventory max_outstanding_messages
290
+
291
+ ##
292
+ # The total byte size of received messages to be collected by subscriber. Default is 100,000,000 (100MB).
293
+ #
294
+ # @return [Integer] The maximum number of bytes.
295
+ #
296
+ def max_outstanding_bytes
297
+ @inventory[:max_outstanding_bytes]
298
+ end
299
+ # @deprecated Use {#max_outstanding_bytes}.
300
+ alias inventory_bytesize max_outstanding_bytes
301
+
302
+ ##
303
+ # Whether to enforce flow control at the client side only or to enforce it at both the client and
304
+ # the server. For more details about flow control see https://cloud.google.com/pubsub/docs/pull#config.
305
+ #
306
+ # @return [Boolean] `true` when only client side flow control is enforced, `false` when both client and
307
+ # server side flow control are enforced.
308
+ #
309
+ def use_legacy_flow_control?
310
+ @inventory[:use_legacy_flow_control]
311
+ end
312
+
313
+ ##
314
+ # The number of seconds that received messages can be held awaiting processing. Default is 3,600 (1 hour).
315
+ #
316
+ # @return [Integer] The maximum number of seconds.
317
+ #
318
+ def max_total_lease_duration
319
+ @inventory[:max_total_lease_duration]
320
+ end
321
+ # @deprecated Use {#max_total_lease_duration}.
322
+ alias inventory_extension max_total_lease_duration
323
+
324
+ ##
325
+ # The maximum amount of time in seconds for a single lease extension attempt. Bounds the delay before a message
326
+ # redelivery if the subscriber fails to extend the deadline. Default is 0 (disabled).
327
+ #
328
+ # @return [Integer] The maximum number of seconds.
329
+ #
330
+ def max_duration_per_lease_extension
331
+ @inventory[:max_duration_per_lease_extension]
332
+ end
333
+
334
+ ##
335
+ # @private
336
+ def stream_inventory
337
+ {
338
+ limit: @inventory[:max_outstanding_messages].fdiv(@streams).ceil,
339
+ bytesize: @inventory[:max_outstanding_bytes].fdiv(@streams).ceil,
340
+ extension: @inventory[:max_total_lease_duration],
341
+ max_duration_per_lease_extension: @inventory[:max_duration_per_lease_extension],
342
+ use_legacy_flow_control: @inventory[:use_legacy_flow_control]
343
+ }
344
+ end
345
+
346
+ # @private returns error object from the stream thread.
347
+ def error! error
348
+ error_callbacks = synchronize do
349
+ @last_error = error
350
+ @error_callbacks
351
+ end
352
+ error_callbacks = default_error_callbacks if error_callbacks.empty?
353
+ error_callbacks.each { |error_callback| error_callback.call error }
354
+ end
355
+
356
+ ##
357
+ # @private
358
+ def to_s
359
+ "(subscription: #{subscription_name}, streams: [#{stream_pool.map(&:to_s).join(', ')}])"
360
+ end
361
+
362
+ ##
363
+ # @private
364
+ def inspect
365
+ "#<#{self.class.name} #{self}>"
366
+ end
367
+
368
+ protected
369
+
370
+ ##
371
+ # Starts a new thread to call wait! (blocking) on each Stream and then stop the TimedUnaryBuffer.
372
+ def wait_stop_buffer_thread!
373
+ synchronize do
374
+ @wait_stop_buffer_thread ||= Thread.new do
375
+ @stream_pool.map(&:wait!)
376
+ # Shutdown the buffer TimerTask (and flush the buffer) after the streams are all stopped.
377
+ @buffer.stop
378
+ end
379
+ end
380
+ end
381
+
382
+ def coerce_inventory inventory
383
+ @inventory = inventory
384
+ if @inventory.is_a? Hash
385
+ @inventory = @inventory.dup
386
+ # Support deprecated field names
387
+ @inventory[:max_outstanding_messages] ||= @inventory.delete :limit
388
+ @inventory[:max_outstanding_bytes] ||= @inventory.delete :bytesize
389
+ @inventory[:max_total_lease_duration] ||= @inventory.delete :extension
390
+ else
391
+ @inventory = { max_outstanding_messages: @inventory }
392
+ end
393
+ @inventory[:max_outstanding_messages] = Integer(@inventory[:max_outstanding_messages] || 1000)
394
+ @inventory[:max_outstanding_bytes] = Integer(@inventory[:max_outstanding_bytes] || 100_000_000)
395
+ @inventory[:max_total_lease_duration] = Integer(@inventory[:max_total_lease_duration] || 3600)
396
+ @inventory[:max_duration_per_lease_extension] = Integer(@inventory[:max_duration_per_lease_extension] || 0)
397
+ @inventory[:use_legacy_flow_control] = @inventory[:use_legacy_flow_control] || false
398
+ end
399
+
400
+ def default_error_callbacks
401
+ # This is memoized to reduce calls to the configuration.
402
+ @default_error_callbacks ||= begin
403
+ error_callback = Google::Cloud::PubSub.configure.on_error
404
+ error_callback ||= Google::Cloud.configure.on_error
405
+ if error_callback
406
+ [error_callback]
407
+ else
408
+ []
409
+ end
410
+ end
411
+ end
412
+ end
413
+ end
414
+
415
+ Pubsub = PubSub unless const_defined? :Pubsub
416
+ end
417
+ end