google-cloud-pubsub 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d3c2b3976af69e59bdb1ea9653f42164db682ce28a929b5325d760c46bab4aa
4
- data.tar.gz: 0f922862ba91d39e1ba8f55a66d2a6699392157ed850e129ed127dc9f63ac1d5
3
+ metadata.gz: 60202a1d96c472dc3bb05992db2ed19da1e34077ceeb5e0a066126a69d569f30
4
+ data.tar.gz: b671179cf63643ec45598fe63b29440504f2d24ce9f2d8495ec0e16e66838809
5
5
  SHA512:
6
- metadata.gz: d33fdcdb157fa0795e6fc28517ccdd26b8b03b3380dd96bd6f931063eae3ac30a5c4d3b5e9dafd32bbc93ee76e4db3544611c4b1ac9a63ad6068422c9bab466e
7
- data.tar.gz: b8218aceaa79d35777e540a43764e7e49474e5dc393c508384f12e4dff09e7d5e1470a8d5a9f2ed6bf96c17d54c63be8489aefbf32babccfeb57a15035867521
6
+ metadata.gz: 01ab09622f6773bfe6a0a5b96171eebb348c71dffd13b06d48eb1754d7cfde3464f81d51051f4a60d5d72c7e39b1b9e746b8417f0d9b86b50dd54280978f3ca4
7
+ data.tar.gz: c0eeb49f436cd8e385ce16b37f5a93445dd29417729624edd572e5a5bc2454c8b3e4504edba9cd73ffe227be64b4b68bfcadceb6e65983b12dfccb222a2879e2
@@ -1,5 +1,24 @@
1
1
  # Release History
2
2
 
3
+ ### 1.1.0 / 2019-10-23
4
+
5
+ #### Features
6
+
7
+ * Add support for Ordering Keys
8
+ * Google Cloud Pub/Sub ordering keys provide the ability to ensure related
9
+ messages are sent to subscribers in the order in which they were published.
10
+ The service guarantees that, for a given ordering key and publisher, messages
11
+ are sent to subscribers in the order in which they were published.
12
+ * Note: At the time of this release, ordering keys are not yet publicly enabled
13
+ and requires special project enablements.
14
+ * Add Google::Cloud::PubSub::Topic#enable_message_ordering! method.
15
+ * Add Google::Cloud::PubSub::Topic#message_ordering? method.
16
+ * Add ordering_key argument to Google::Cloud::PubSub::Topic#publish_async method.
17
+ * Add Google::Cloud::PubSub::Topic#resume_publish method.
18
+ * Add message_ordering argument to Google::Cloud::PubSub::Topic#subscribe method.
19
+ * Add Google::Cloud::PubSub::Subscription#message_ordering? method.
20
+ * Update Ruby dependency to minimum of 2.4.
21
+
3
22
  ### 1.0.2 / 2019-10-10
4
23
 
5
24
  #### Bug Fixes
@@ -24,7 +24,7 @@ be able to accept your pull requests.
24
24
  In order to use the google-cloud-pubsub console and run the project's tests,
25
25
  there is a small amount of setup:
26
26
 
27
- 1. Install Ruby. google-cloud-pubsub requires Ruby 2.3+. You may choose to
27
+ 1. Install Ruby. google-cloud-pubsub requires Ruby 2.4+. You may choose to
28
28
  manage your Ruby and gem installations with [RVM](https://rvm.io/),
29
29
  [rbenv](https://github.com/rbenv/rbenv), or
30
30
  [chruby](https://github.com/postmodern/chruby).
@@ -161,7 +161,7 @@ msgs = topic.publish do |batch|
161
161
  end
162
162
  ```
163
163
 
164
- ## Receiving messages
164
+ ## Receiving Messages
165
165
 
166
166
  Messages can be streamed from a subscription with a subscriber object that is
167
167
  created using `listen`. (See {Google::Cloud::PubSub::Subscription#listen
@@ -316,6 +316,88 @@ received_messages = sub.pull
316
316
  sub.modify_ack_deadline 120, received_messages
317
317
  ```
318
318
 
319
+ ## Using Ordering Keys
320
+
321
+ Google Cloud Pub/Sub ordering keys provide the ability to ensure related
322
+ messages are sent to subscribers in the order in which they were published.
323
+ Messages can be tagged with an ordering key, a string that identifies related
324
+ messages for which publish order should be respected. The service guarantees
325
+ that, for a given ordering key and publisher, messages are sent to subscribers
326
+ in the order in which they were published. Ordering does not require sacrificing
327
+ high throughput or scalability, as the service automatically distributes
328
+ messages for different ordering keys across subscribers.
329
+
330
+ Note: At the time of this release, ordering keys are not yet publicly enabled
331
+ and requires special project enablements.
332
+
333
+ ### Publishing Ordered Messages
334
+
335
+ To use ordering keys when publishing messages, a call to
336
+ {Google::Cloud::PubSub::Topic#enable_message_ordering!
337
+ Topic#enable_message_ordering!} must be made and the `ordering_key` argument
338
+ must be provided when calling {Google::Cloud::PubSub::Topic#publish_async
339
+ Topic#publish_async}.
340
+
341
+ ```ruby
342
+ require "google/cloud/pubsub"
343
+
344
+ pubsub = Google::Cloud::PubSub.new
345
+
346
+ topic = pubsub.topic "my-ordered-topic"
347
+
348
+ # Ensure that message ordering is enabled.
349
+ topic.enable_message_ordering!
350
+
351
+ # Publish an ordered message with an ordering key.
352
+ topic.publish_async "task completed",
353
+ ordering_key: "task-key"
354
+
355
+ # Shut down the publisher when ready to stop publishing messages.
356
+ topic.async_publisher.stop.wait!
357
+ ```
358
+
359
+ ### Handling errors with Ordered Keys
360
+
361
+ Ordered messages that fail to publish to the Pub/Sub API due to error will put
362
+ the `ordering_key` in a failed state, and future calls to
363
+ {Google::Cloud::PubSub::Topic#publish_async Topic#publish_async} with the
364
+ `ordering_key` will raise {Google::Cloud::PubSub::OrderingKeyError
365
+ OrderingKeyError}. To allow future messages with the `ordering_key` to be
366
+ published, the `ordering_key` must be passed to
367
+ {Google::Cloud::PubSub::Topic#resume_publish Topic#resume_publish}.
368
+
369
+ ### Receiving Ordered Messages
370
+
371
+ To use ordering keys when subscribing to messages, the subscription must be
372
+ created with message ordering enabled (See
373
+ {Google::Cloud::PubSub::Topic#subscribe Topic#subscribe} and
374
+ {Google::Cloud::PubSub::Subscription#message_ordering?
375
+ Subscription#message_ordering?}) before calling
376
+ {Google::Cloud::PubSub::Subscription#listen Subscription#listen}. When enabled,
377
+ the subscriber will deliver messages with the same `ordering_key` in the order
378
+ they were published.
379
+
380
+ ```ruby
381
+ require "google/cloud/pubsub"
382
+
383
+ pubsub = Google::Cloud::PubSub.new
384
+
385
+ sub = pubsub.subscription "my-ordered-topic-sub"
386
+ sub.message_ordering? #=> true
387
+
388
+ subscriber = sub.listen do |received_message|
389
+ # Messsages with the same ordering_key are received
390
+ # in the order in which they were published.
391
+ received_message.acknowledge!
392
+ end
393
+
394
+ # Start background threads that will call block passed to listen.
395
+ subscriber.start
396
+
397
+ # Shut down the subscriber when ready to stop receiving messages.
398
+ subscriber.stop.wait!
399
+ ```
400
+
319
401
  ## Minimizing API calls before receiving and acknowledging messages
320
402
 
321
403
  A subscription object can be created without making any API calls by providing
@@ -64,9 +64,7 @@ module Google
64
64
  #
65
65
  def pubsub scope: nil, timeout: nil, client_config: nil
66
66
  timeout ||= @timeout
67
- Google::Cloud.pubsub @project, @keyfile, scope: scope,
68
- timeout: timeout,
69
- client_config: client_config
67
+ Google::Cloud.pubsub @project, @keyfile, scope: scope, timeout: timeout, client_config: client_config
70
68
  end
71
69
 
72
70
  ##
@@ -108,10 +106,8 @@ module Google
108
106
  def self.pubsub project_id = nil, credentials = nil, scope: nil,
109
107
  timeout: nil, client_config: nil
110
108
  require "google/cloud/pubsub"
111
- Google::Cloud::PubSub.new project_id: project_id,
112
- credentials: credentials,
113
- scope: scope, timeout: timeout,
114
- client_config: client_config
109
+ Google::Cloud::PubSub.new project_id: project_id, credentials: credentials,
110
+ scope: scope, timeout: timeout, client_config: client_config
115
111
  end
116
112
  end
117
113
  end
@@ -123,8 +119,7 @@ Google::Cloud.configure.add_config! :pubsub do |config|
123
119
  end
124
120
  default_creds = Google::Cloud::Config.deferred do
125
121
  Google::Cloud::Config.credentials_from_env(
126
- "PUBSUB_CREDENTIALS", "PUBSUB_CREDENTIALS_JSON",
127
- "PUBSUB_KEYFILE", "PUBSUB_KEYFILE_JSON"
122
+ "PUBSUB_CREDENTIALS", "PUBSUB_CREDENTIALS_JSON", "PUBSUB_KEYFILE", "PUBSUB_KEYFILE_JSON"
128
123
  )
129
124
  end
130
125
  default_emulator = Google::Cloud::Config.deferred do
@@ -133,15 +128,12 @@ Google::Cloud.configure.add_config! :pubsub do |config|
133
128
 
134
129
  config.add_field! :project_id, default_project, match: String, allow_nil: true
135
130
  config.add_alias! :project, :project_id
136
- config.add_field! :credentials, default_creds,
137
- match: [String, Hash, Google::Auth::Credentials],
138
- allow_nil: true
131
+ config.add_field! :credentials, default_creds, match: [String, Hash, Google::Auth::Credentials], allow_nil: true
139
132
  config.add_alias! :keyfile, :credentials
140
133
  config.add_field! :scope, nil, match: [String, Array]
141
134
  config.add_field! :timeout, nil, match: Integer
142
135
  config.add_field! :client_config, nil, match: Hash
143
- config.add_field! :emulator_host, default_emulator,
144
- match: String, allow_nil: true
136
+ config.add_field! :emulator_host, default_emulator, match: String, allow_nil: true
145
137
  config.add_field! :on_error, nil, match: Proc
146
138
  config.add_field! :endpoint, nil, match: String
147
139
  end
@@ -77,9 +77,8 @@ module Google
77
77
  # topic = pubsub.topic "my-topic"
78
78
  # topic.publish "task completed"
79
79
  #
80
- def self.new project_id: nil, credentials: nil, scope: nil, timeout: nil,
81
- client_config: nil, endpoint: nil, emulator_host: nil,
82
- project: nil, keyfile: nil
80
+ def self.new project_id: nil, credentials: nil, scope: nil, timeout: nil, client_config: nil, endpoint: nil,
81
+ emulator_host: nil, project: nil, keyfile: nil
83
82
  project_id ||= (project || default_project_id)
84
83
  scope ||= configure.scope
85
84
  timeout ||= configure.timeout
@@ -93,9 +92,7 @@ module Google
93
92
 
94
93
  return PubSub::Project.new(
95
94
  PubSub::Service.new(
96
- project_id, :this_channel_is_insecure,
97
- host: emulator_host, timeout: timeout,
98
- client_config: client_config
95
+ project_id, :this_channel_is_insecure, host: emulator_host, timeout: timeout, client_config: client_config
99
96
  )
100
97
  )
101
98
  end
@@ -105,17 +102,13 @@ module Google
105
102
  credentials = PubSub::Credentials.new credentials, scope: scope
106
103
  end
107
104
 
108
- if credentials.respond_to? :project_id
109
- project_id ||= credentials.project_id
110
- end
105
+ project_id ||= credentials.project_id if credentials.respond_to? :project_id
111
106
  project_id = project_id.to_s # Always cast to a string
112
107
  raise ArgumentError, "project_id is missing" if project_id.empty?
113
108
 
114
109
  PubSub::Project.new(
115
110
  PubSub::Service.new(
116
- project_id, credentials, timeout: timeout,
117
- host: endpoint,
118
- client_config: client_config
111
+ project_id, credentials, timeout: timeout, host: endpoint, client_config: client_config
119
112
  )
120
113
  )
121
114
  end
@@ -15,8 +15,11 @@
15
15
 
16
16
  require "monitor"
17
17
  require "concurrent"
18
+ require "google/cloud/pubsub/errors"
19
+ require "google/cloud/pubsub/async_publisher/batch"
18
20
  require "google/cloud/pubsub/publish_result"
19
21
  require "google/cloud/pubsub/service"
22
+ require "google/cloud/pubsub/convert"
20
23
 
21
24
  module Google
22
25
  module Cloud
@@ -68,8 +71,7 @@ module Google
68
71
 
69
72
  ##
70
73
  # @private Create a new instance of the object.
71
- def initialize topic_name, service, max_bytes: 10000000,
72
- max_messages: 1000, interval: 0.25, threads: {}
74
+ def initialize topic_name, service, max_bytes: 10_000_000, max_messages: 1000, interval: 0.25, threads: {}
73
75
  @topic_name = service.topic_path topic_name
74
76
  @service = service
75
77
 
@@ -79,6 +81,14 @@ module Google
79
81
  @publish_threads = (threads[:publish] || 4).to_i
80
82
  @callback_threads = (threads[:callback] || 8).to_i
81
83
 
84
+ @published_at = nil
85
+ @publish_thread_pool = Concurrent::ThreadPoolExecutor.new max_threads: @publish_threads
86
+ @callback_thread_pool = Concurrent::ThreadPoolExecutor.new max_threads: @callback_threads
87
+ @thread = Thread.new { run_background }
88
+
89
+ @ordered = false
90
+ @batches = {}
91
+
82
92
  @cond = new_cond
83
93
 
84
94
  # init MonitorMixin
@@ -89,29 +99,45 @@ module Google
89
99
  # Add a message to the async publisher to be published to the topic.
90
100
  # Messages will be collected in batches and published together.
91
101
  # See {Google::Cloud::PubSub::Topic#publish_async}
92
- def publish data = nil, attributes = {}, &block
93
- msg = create_pubsub_message data, attributes
102
+ #
103
+ # @param [String, File] data The message payload. This will be converted
104
+ # to bytes encoded as ASCII-8BIT.
105
+ # @param [Hash] attributes Optional attributes for the message.
106
+ # @param [String] ordering_key Identifies related messages for which
107
+ # publish order should be respected.
108
+ # @yield [result] the callback for when the message has been published
109
+ # @yieldparam [PublishResult] result the result of the asynchronous
110
+ # publish
111
+ # @raise [Google::Cloud::PubSub::AsyncPublisherStopped] when the
112
+ # publisher is stopped. (See {#stop} and {#stopped?}.)
113
+ # @raise [Google::Cloud::PubSub::OrderedMessagesDisabled] when
114
+ # publishing a message with an `ordering_key` but ordered messages are
115
+ # not enabled. (See {#message_ordering?} and
116
+ # {#enable_message_ordering!}.)
117
+ # @raise [Google::Cloud::PubSub::OrderingKeyError] when publishing a
118
+ # message with an `ordering_key` that has already failed when
119
+ # publishing. Use {#resume_publish} to allow this `ordering_key` to be
120
+ # published again.
121
+ #
122
+ def publish data = nil, attributes = nil, ordering_key: nil, **extra_attrs, &callback
123
+ msg = Convert.pubsub_message data, attributes, ordering_key, extra_attrs
94
124
 
95
125
  synchronize do
96
- raise "Can't publish when stopped." if @stopped
97
-
98
- if @batch.nil?
99
- @batch ||= Batch.new self
100
- @batch.add msg, block
101
- else
102
- unless @batch.try_add msg, block
103
- publish_batch!
104
- @batch = Batch.new self
105
- @batch.add msg, block
106
- end
126
+ raise AsyncPublisherStopped if @stopped
127
+ raise OrderedMessagesDisabled if !@ordered && !msg.ordering_key.empty? # default is empty string
128
+
129
+ batch = resolve_batch_for_message msg
130
+ raise OrderingKeyError, batch.ordering_key if batch.canceled?
131
+ batch_action = batch.add msg, callback
132
+ if batch_action == :full
133
+ publish_batches!
134
+ elsif @published_at.nil?
135
+ # Set initial time to now to start the background counter
136
+ @published_at = Time.now
107
137
  end
108
-
109
- init_resources!
110
-
111
- publish_batch! if @batch.ready?
112
-
113
138
  @cond.signal
114
139
  end
140
+
115
141
  nil
116
142
  end
117
143
 
@@ -127,9 +153,9 @@ module Google
127
153
  break if @stopped
128
154
 
129
155
  @stopped = true
130
- publish_batch!
156
+ publish_batches! stop: true
131
157
  @cond.signal
132
- @publish_thread_pool.shutdown if @publish_thread_pool
158
+ @publish_thread_pool.shutdown
133
159
  end
134
160
 
135
161
  self
@@ -149,14 +175,10 @@ module Google
149
175
  # @return [AsyncPublisher] returns self so calls can be chained.
150
176
  def wait! timeout = nil
151
177
  synchronize do
152
- if @publish_thread_pool
153
- @publish_thread_pool.wait_for_termination timeout
154
- end
178
+ @publish_thread_pool.wait_for_termination timeout
155
179
 
156
- if @callback_thread_pool
157
- @callback_thread_pool.shutdown
158
- @callback_thread_pool.wait_for_termination timeout
159
- end
180
+ @callback_thread_pool.shutdown
181
+ @callback_thread_pool.wait_for_termination timeout
160
182
  end
161
183
 
162
184
  self
@@ -185,7 +207,7 @@ module Google
185
207
  # @return [AsyncPublisher] returns self so calls can be chained.
186
208
  def flush
187
209
  synchronize do
188
- publish_batch!
210
+ publish_batches!
189
211
  @cond.signal
190
212
  end
191
213
 
@@ -208,33 +230,63 @@ module Google
208
230
  synchronize { @stopped }
209
231
  end
210
232
 
211
- protected
233
+ ##
234
+ # Enables message ordering for messages with ordering keys. When
235
+ # enabled, messages published with the same `ordering_key` will be
236
+ # delivered in the order they were published.
237
+ #
238
+ # See {#message_ordering?}. See {Topic#publish_async},
239
+ # {Subscription#listen}, and {Message#ordering_key}.
240
+ #
241
+ def enable_message_ordering!
242
+ synchronize { @ordered = true }
243
+ end
212
244
 
213
- # rubocop:disable Naming/MemoizedInstanceVariableName
245
+ ##
246
+ # Whether message ordering for messages with ordering keys has been
247
+ # enabled. When enabled, messages published with the same `ordering_key`
248
+ # will be delivered in the order they were published. When disabled,
249
+ # messages may be delivered in any order.
250
+ #
251
+ # See {#enable_message_ordering!}. See {Topic#publish_async},
252
+ # {Subscription#listen}, and {Message#ordering_key}.
253
+ #
254
+ # @return [Boolean]
255
+ #
256
+ def message_ordering?
257
+ synchronize { @ordered }
258
+ end
214
259
 
215
- def init_resources!
216
- @first_published_at ||= Time.now
217
- @publish_thread_pool ||= Concurrent::ThreadPoolExecutor.new \
218
- max_threads: @publish_threads
219
- @callback_thread_pool ||= Concurrent::ThreadPoolExecutor.new \
220
- max_threads: @callback_threads
221
- @thread ||= Thread.new { run_background }
260
+ ##
261
+ # Resume publishing ordered messages for the provided ordering key.
262
+ #
263
+ # @param [String] ordering_key Identifies related messages for which
264
+ # publish order should be respected.
265
+ #
266
+ # @return [boolean] `true` when resumed, `false` otherwise.
267
+ #
268
+ def resume_publish ordering_key
269
+ synchronize do
270
+ batch = resolve_batch_for_ordering_key ordering_key
271
+ return if batch.nil?
272
+ batch.resume!
273
+ end
222
274
  end
223
275
 
224
- # rubocop:enable Naming/MemoizedInstanceVariableName
276
+ protected
225
277
 
226
278
  def run_background
227
279
  synchronize do
228
280
  until @stopped
229
- if @batch.nil?
281
+ if @published_at.nil?
230
282
  @cond.wait
231
283
  next
232
284
  end
233
285
 
234
- time_since_first_publish = Time.now - @first_published_at
286
+ time_since_first_publish = Time.now - @published_at
235
287
  if time_since_first_publish > @interval
236
- # interval met, publish the batch...
237
- publish_batch!
288
+ # interval met, flush the batches...
289
+ publish_batches!
238
290
  @cond.wait
239
291
  else
240
292
  # still waiting for the interval to publish the batch...
@@ -245,40 +297,93 @@ module Google
245
297
  end
246
298
  end
247
299
 
248
- def publish_batch!
249
- return unless @batch
300
+ def resolve_batch_for_message msg
301
+ @batches[msg.ordering_key] ||= Batch.new self, msg.ordering_key
302
+ end
250
303
 
251
- publish_batch_async @topic_name, @batch
252
- @batch = nil
253
- @first_published_at = nil
304
+ def resolve_batch_for_ordering_key ordering_key
305
+ @batches[ordering_key]
306
+ end
307
+
308
+ def publish_batches! stop: nil
309
+ @batches.reject! { |_ordering_key, batch| batch.empty? }
310
+ @batches.values.each do |batch|
311
+ ready = batch.publish! stop: stop
312
+ publish_batch_async @topic_name, batch if ready
313
+ end
314
+ # Set published_at to nil to wait indefinitely
315
+ @published_at = nil
254
316
  end
255
317
 
256
318
  def publish_batch_async topic_name, batch
319
+ # TODO: raise unless @publish_thread_pool.running?
257
320
  return unless @publish_thread_pool.running?
258
321
 
259
322
  Concurrent::Promises.future_on(
260
323
  @publish_thread_pool, topic_name, batch
261
- ) do |t_name, btch|
262
- publish_batch_sync t_name, btch
263
- end
324
+ ) { |t, b| publish_batch_sync t, b }
264
325
  end
265
326
 
327
+ # rubocop:disable Metrics/AbcSize
328
+ # rubocop:disable Metrics/MethodLength
329
+
266
330
  def publish_batch_sync topic_name, batch
267
- grpc = @service.publish topic_name, batch.messages
268
- batch.items.zip Array(grpc.message_ids) do |item, id|
269
- next unless item.callback
331
+ # The only batch methods that are safe to call from the loop are
332
+ # rebalance! and reset! because they are the only methods that are
333
+ # synchronized.
334
+ loop do
335
+ items = batch.rebalance!
336
+
337
+ unless items.empty?
338
+ grpc = @service.publish topic_name, items.map(&:msg)
339
+ items.zip Array(grpc.message_ids) do |item, id|
340
+ next unless item.callback
341
+
342
+ item.msg.message_id = id
343
+ publish_result = PublishResult.from_grpc item.msg
344
+ execute_callback_async item.callback, publish_result
345
+ end
346
+ end
270
347
 
271
- item.msg.message_id = id
272
- publish_result = PublishResult.from_grpc item.msg
273
- execute_callback_async item.callback, publish_result
348
+ break unless batch.reset!
274
349
  end
275
350
  rescue StandardError => e
276
- batch.items.each do |item|
351
+ items = batch.items
352
+
353
+ unless batch.ordering_key.empty?
354
+ retry if publish_batch_error_retryable? e
355
+ # Cancel the batch if the error is not to be retried.
356
+ begin
357
+ raise OrderingKeyError, batch.ordering_key
358
+ rescue OrderingKeyError => e
359
+ # The existing e variable is not set to OrderingKeyError
360
+ # Get all unsent messages for the callback
361
+ items = batch.cancel!
362
+ end
363
+ end
364
+
365
+ items.each do |item|
277
366
  next unless item.callback
278
367
 
279
368
  publish_result = PublishResult.from_error item.msg, e
280
369
  execute_callback_async item.callback, publish_result
281
370
  end
371
+
372
+ # publish will retry indefinitely, as long as there are unsent items.
373
+ retry if batch.reset!
374
+ end
375
+
376
+ # rubocop:enable Metrics/AbcSize
377
+ # rubocop:enable Metrics/MethodLength
378
+
379
+ PUBLISH_RETRY_ERRORS = [
380
+ GRPC::Cancelled, GRPC::DeadlineExceeded, GRPC::Internal,
381
+ GRPC::ResourceExhausted, GRPC::Unauthenticated, GRPC::Unavailable,
382
+ GRPC::Core::CallError
383
+ ].freeze
384
+
385
+ def publish_batch_error_retryable? error
386
+ PUBLISH_RETRY_ERRORS.any? { |klass| error.is_a? klass }
282
387
  end
283
388
 
284
389
  def execute_callback_async callback, publish_result
@@ -290,79 +395,6 @@ module Google
290
395
  cback.call p_result
291
396
  end
292
397
  end
293
-
294
- def create_pubsub_message data, attributes
295
- attributes ||= {}
296
- if data.is_a?(::Hash) && attributes.empty?
297
- attributes = data
298
- data = nil
299
- end
300
- # Convert IO-ish objects to strings
301
- if data.respond_to?(:read) && data.respond_to?(:rewind)
302
- data.rewind
303
- data = data.read
304
- end
305
- # Convert data to encoded byte array to match the protobuf defn
306
- data_bytes = \
307
- String(data).dup.force_encoding(Encoding::ASCII_8BIT).freeze
308
-
309
- # Convert attributes to strings to match the protobuf definition
310
- attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
311
-
312
- Google::Cloud::PubSub::V1::PubsubMessage.new data: data_bytes,
313
- attributes: attributes
314
- end
315
-
316
- ##
317
- # @private
318
- class Batch
319
- attr_reader :messages, :callbacks
320
-
321
- def initialize publisher
322
- @publisher = publisher
323
- @messages = []
324
- @callbacks = []
325
- @total_message_bytes = publisher.topic_name.bytesize + 2
326
- end
327
-
328
- def add msg, callback
329
- @messages << msg
330
- @callbacks << callback
331
- @total_message_bytes += msg.to_proto.bytesize + 2
332
- end
333
-
334
- def try_add msg, callback
335
- new_message_count = total_message_count + 1
336
- new_message_bytes = total_message_bytes + msg.to_proto.bytesize + 2
337
- if new_message_count > @publisher.max_messages ||
338
- new_message_bytes >= @publisher.max_bytes
339
- return false
340
- end
341
- add msg, callback
342
- true
343
- end
344
-
345
- def ready?
346
- total_message_count >= @publisher.max_messages ||
347
- total_message_bytes >= @publisher.max_bytes
348
- end
349
-
350
- def total_message_count
351
- @messages.count
352
- end
353
-
354
- def total_message_bytes
355
- @total_message_bytes
356
- end
357
-
358
- def items
359
- @messages.zip(@callbacks).map do |msg, callback|
360
- Item.new msg, callback
361
- end
362
- end
363
-
364
- Item = Struct.new :msg, :callback
365
- end
366
398
  end
367
399
  end
368
400