google-cloud-pubsub 0.26.0 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.
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