google-cloud-pubsub 1.0.2 → 2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +16 -54
  3. data/CHANGELOG.md +464 -0
  4. data/CONTRIBUTING.md +328 -116
  5. data/EMULATOR.md +1 -1
  6. data/LOGGING.md +94 -2
  7. data/OVERVIEW.md +121 -68
  8. data/TROUBLESHOOTING.md +2 -8
  9. data/lib/google/cloud/pubsub/acknowledge_result.rb +79 -0
  10. data/lib/google/cloud/pubsub/async_publisher/batch.rb +319 -0
  11. data/lib/google/cloud/pubsub/async_publisher.rb +231 -156
  12. data/lib/google/cloud/pubsub/batch_publisher.rb +60 -30
  13. data/lib/google/cloud/pubsub/convert.rb +33 -7
  14. data/lib/google/cloud/pubsub/credentials.rb +2 -2
  15. data/lib/google/cloud/pubsub/errors.rb +93 -0
  16. data/lib/google/cloud/pubsub/flow_controller.rb +137 -0
  17. data/lib/google/cloud/pubsub/message.rb +45 -4
  18. data/lib/google/cloud/pubsub/policy.rb +3 -2
  19. data/lib/google/cloud/pubsub/project.rb +316 -49
  20. data/lib/google/cloud/pubsub/publish_result.rb +6 -1
  21. data/lib/google/cloud/pubsub/received_message.rb +171 -10
  22. data/lib/google/cloud/pubsub/retry_policy.rb +88 -0
  23. data/lib/google/cloud/pubsub/schema/list.rb +180 -0
  24. data/lib/google/cloud/pubsub/schema.rb +310 -0
  25. data/lib/google/cloud/pubsub/service.rb +285 -269
  26. data/lib/google/cloud/pubsub/snapshot/list.rb +4 -6
  27. data/lib/google/cloud/pubsub/snapshot.rb +5 -2
  28. data/lib/google/cloud/pubsub/subscriber/inventory.rb +69 -32
  29. data/lib/google/cloud/pubsub/subscriber/sequencer.rb +115 -0
  30. data/lib/google/cloud/pubsub/subscriber/stream.rb +108 -49
  31. data/lib/google/cloud/pubsub/subscriber/timed_unary_buffer.rb +191 -30
  32. data/lib/google/cloud/pubsub/subscriber.rb +155 -45
  33. data/lib/google/cloud/pubsub/subscription/list.rb +4 -6
  34. data/lib/google/cloud/pubsub/subscription/push_config.rb +55 -31
  35. data/lib/google/cloud/pubsub/subscription.rb +561 -77
  36. data/lib/google/cloud/pubsub/topic/list.rb +4 -6
  37. data/lib/google/cloud/pubsub/topic.rb +372 -52
  38. data/lib/google/cloud/pubsub/version.rb +1 -1
  39. data/lib/google/cloud/pubsub.rb +35 -46
  40. data/lib/google-cloud-pubsub.rb +21 -27
  41. metadata +26 -189
  42. data/lib/google/cloud/pubsub/v1/credentials.rb +0 -41
  43. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/iam_policy.rb +0 -21
  44. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/options.rb +0 -21
  45. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/policy.rb +0 -21
  46. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +0 -91
  47. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/empty.rb +0 -29
  48. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +0 -222
  49. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +0 -113
  50. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +0 -744
  51. data/lib/google/cloud/pubsub/v1/doc/google/type/expr.rb +0 -19
  52. data/lib/google/cloud/pubsub/v1/publisher_client.rb +0 -786
  53. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +0 -105
  54. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +0 -1385
  55. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +0 -138
  56. data/lib/google/cloud/pubsub/v1.rb +0 -17
  57. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -249
  58. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -211
@@ -124,17 +124,15 @@ module Google
124
124
  # puts topic.name
125
125
  # end
126
126
  #
127
- def all request_limit: nil
127
+ def all request_limit: nil, &block
128
128
  request_limit = request_limit.to_i if request_limit
129
- unless block_given?
130
- return enum_for :all, request_limit: request_limit
131
- end
129
+ return enum_for :all, request_limit: request_limit unless block_given?
132
130
  results = self
133
131
  loop do
134
- results.each { |r| yield r }
132
+ results.each(&block)
135
133
  if request_limit
136
134
  request_limit -= 1
137
- break if request_limit < 0
135
+ break if request_limit.negative?
138
136
  end
139
137
  break unless results.next?
140
138
  results = results.next
@@ -19,6 +19,7 @@ require "google/cloud/pubsub/async_publisher"
19
19
  require "google/cloud/pubsub/batch_publisher"
20
20
  require "google/cloud/pubsub/subscription"
21
21
  require "google/cloud/pubsub/policy"
22
+ require "google/cloud/pubsub/retry_policy"
22
23
 
23
24
  module Google
24
25
  module Cloud
@@ -77,17 +78,17 @@ module Google
77
78
  # end
78
79
  # end
79
80
  #
80
- # topic.async_publisher.stop.wait!
81
+ # topic.async_publisher.stop!
81
82
  #
82
83
  def async_publisher
83
84
  @async_publisher
84
85
  end
85
86
 
86
87
  ##
87
- # The name of the topic in the form of
88
- # "/projects/project-identifier/topics/topic-name".
88
+ # The name of the topic.
89
89
  #
90
- # @return [String]
90
+ # @return [String] A fully-qualified topic name in the form
91
+ # `projects/{project_id}/topics/{topic_id}`.
91
92
  #
92
93
  def name
93
94
  return @resource_name if reference?
@@ -126,8 +127,7 @@ module Google
126
127
  #
127
128
  def labels= new_labels
128
129
  raise ArgumentError, "Value must be a Hash" if new_labels.nil?
129
- update_grpc = Google::Cloud::PubSub::V1::Topic.new \
130
- name: name, labels: new_labels
130
+ update_grpc = Google::Cloud::PubSub::V1::Topic.new name: name, labels: new_labels
131
131
  @grpc = service.update_topic update_grpc, :labels
132
132
  @resource_name = nil
133
133
  end
@@ -176,8 +176,7 @@ module Google
176
176
  # topic.kms_key = key_name
177
177
  #
178
178
  def kms_key= new_kms_key_name
179
- update_grpc = Google::Cloud::PubSub::V1::Topic.new \
180
- name: name, kms_key_name: new_kms_key_name
179
+ update_grpc = Google::Cloud::PubSub::V1::Topic.new name: name, kms_key_name: new_kms_key_name
181
180
  @grpc = service.update_topic update_grpc, :kms_key_name
182
181
  @resource_name = nil
183
182
  end
@@ -229,13 +228,120 @@ module Google
229
228
  #
230
229
  def persistence_regions= new_persistence_regions
231
230
  update_grpc = Google::Cloud::PubSub::V1::Topic.new \
232
- name: name, message_storage_policy: {
233
- allowed_persistence_regions: Array(new_persistence_regions)
234
- }
231
+ name: name, message_storage_policy: { allowed_persistence_regions: Array(new_persistence_regions) }
235
232
  @grpc = service.update_topic update_grpc, :message_storage_policy
236
233
  @resource_name = nil
237
234
  end
238
235
 
236
+ ##
237
+ # The name of the schema that messages published should be validated against, if schema settings are configured
238
+ # for the topic. The value is a fully-qualified schema name in the form
239
+ # `projects/{project_id}/schemas/{schema_id}`. If present, {#message_encoding} should also be present. The value
240
+ # of this field will be `_deleted-schema_` if the schema has been deleted.
241
+ #
242
+ # Makes an API call to retrieve the schema settings when called on a reference object. See {#reference?}.
243
+ #
244
+ # @return [String, nil] The schema name, or `nil` if schema settings are not configured for the topic.
245
+ #
246
+ # @example
247
+ # require "google/cloud/pubsub"
248
+ #
249
+ # pubsub = Google::Cloud::PubSub.new
250
+ #
251
+ # topic = pubsub.topic "my-topic"
252
+ #
253
+ # topic.schema_name #=> "projects/my-project/schemas/my-schema"
254
+ #
255
+ def schema_name
256
+ ensure_grpc!
257
+ @grpc.schema_settings&.schema
258
+ end
259
+
260
+ ##
261
+ # The encoding of messages validated against the schema identified by {#schema_name}. If present, {#schema_name}
262
+ # should also be present. Values include:
263
+ #
264
+ # * `JSON` - JSON encoding.
265
+ # * `BINARY` - Binary encoding, as defined by the schema type. For some schema types, binary encoding may not be
266
+ # available.
267
+ #
268
+ # Makes an API call to retrieve the schema settings when called on a reference object. See {#reference?}.
269
+ #
270
+ # @return [Symbol, nil] The schema encoding, or `nil` if schema settings are not configured for the topic.
271
+ #
272
+ # @example
273
+ # require "google/cloud/pubsub"
274
+ #
275
+ # pubsub = Google::Cloud::PubSub.new
276
+ #
277
+ # topic = pubsub.topic "my-topic"
278
+ #
279
+ # topic.message_encoding #=> :JSON
280
+ #
281
+ def message_encoding
282
+ ensure_grpc!
283
+ @grpc.schema_settings&.encoding
284
+ end
285
+
286
+ ##
287
+ # Checks if the encoding of messages in the schema settings is `BINARY`. See {#message_encoding}.
288
+ #
289
+ # Makes an API call to retrieve the schema settings when called on a reference object. See {#reference?}.
290
+ #
291
+ # @return [Boolean] `true` when `BINARY`, `false` if not `BINARY` or schema settings is not set.
292
+ #
293
+ def message_encoding_binary?
294
+ message_encoding.to_s.upcase == "BINARY"
295
+ end
296
+
297
+ ##
298
+ # Checks if the encoding of messages in the schema settings is `JSON`. See {#message_encoding}.
299
+ #
300
+ # Makes an API call to retrieve the schema settings when called on a reference object. See {#reference?}.
301
+ #
302
+ # @return [Boolean] `true` when `JSON`, `false` if not `JSON` or schema settings is not set.
303
+ #
304
+ def message_encoding_json?
305
+ message_encoding.to_s.upcase == "JSON"
306
+ end
307
+
308
+ ##
309
+ # Indicates the minimum number of seconds to retain a message after it is
310
+ # published to the topic. If this field is set, messages published to the topic
311
+ # within the `retention` number of seconds are always available to subscribers.
312
+ # For instance, it allows any attached subscription to [seek to a
313
+ # timestamp](https://cloud.google.com/pubsub/docs/replay-overview#seek_to_a_time)
314
+ # that is up to `retention` number of seconds in the past. If this field is
315
+ # not set, message retention is controlled by settings on individual
316
+ # subscriptions. Cannot be less than 600 (10 minutes) or more than 604,800 (7 days).
317
+ # See {#retention=}.
318
+ #
319
+ # Makes an API call to retrieve the retention value when called on a
320
+ # reference object. See {#reference?}.
321
+ #
322
+ # @return [Numeric, nil] The message retention duration in seconds, or `nil` if not set.
323
+ #
324
+ def retention
325
+ ensure_grpc!
326
+ Convert.duration_to_number @grpc.message_retention_duration
327
+ end
328
+
329
+ ##
330
+ # Sets the message retention duration in seconds. If set to a positive duration
331
+ # between 600 (10 minutes) and 604,800 (7 days), inclusive, the message retention
332
+ # duration is changed. If set to `nil`, this clears message retention duration
333
+ # from the topic. See {#retention}.
334
+ #
335
+ # @param [Numeric, nil] new_retention The new message retention duration value.
336
+ #
337
+ def retention= new_retention
338
+ new_retention_duration = Convert.number_to_duration new_retention
339
+ update_grpc = Google::Cloud::PubSub::V1::Topic.new name: name,
340
+ message_retention_duration: new_retention_duration
341
+ @grpc = service.update_topic update_grpc, :message_retention_duration
342
+ @resource_name = nil
343
+ end
344
+
239
345
  ##
240
346
  # Permanently deletes the topic.
241
347
  #
@@ -258,28 +364,38 @@ module Google
258
364
  ##
259
365
  # Creates a new {Subscription} object on the current Topic.
260
366
  #
261
- # @param [String] subscription_name Name of the new subscription. Must
262
- # start with a letter, and contain only letters ([A-Za-z]), numbers
263
- # ([0-9], dashes (-), underscores (_), periods (.), tildes (~), plus
264
- # (+) or percent signs (%). It must be between 3 and 255 characters in
265
- # length, and it must not start with "goog". Required.
266
- # @param [Integer] deadline The maximum number of seconds after a
367
+ # @option options [String] subscription_name Name of the new subscription. Required.
368
+ # The value can be a simple subscription ID (relative name), in which
369
+ # case the current project ID will be supplied, or a fully-qualified
370
+ # subscription name in the form
371
+ # `projects/{project_id}/subscriptions/{subscription_id}`.
372
+ #
373
+ # The subscription ID (relative name) must start with a letter, and
374
+ # contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),
375
+ # underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent
376
+ # signs (`%`). It must be between 3 and 255 characters in length, and
377
+ # it must not start with `goog`.
378
+ # @option options [Integer] deadline The maximum number of seconds after a
267
379
  # subscriber receives a message before the subscriber should
268
380
  # acknowledge the message.
269
- # @param [Boolean] retain_acked Indicates whether to retain acknowledged
381
+ # @option options [Boolean] retain_acked Indicates whether to retain acknowledged
270
382
  # messages. If `true`, then messages are not expunged from the
271
383
  # subscription's backlog, even if they are acknowledged, until they
272
384
  # fall out of the `retention` window. Default is `false`.
273
- # @param [Numeric] retention How long to retain unacknowledged messages
385
+ # @option options [Numeric] retention How long to retain unacknowledged messages
274
386
  # in the subscription's backlog, from the moment a message is
275
387
  # published. If `retain_acked` is `true`, then this also configures
276
388
  # the retention of acknowledged messages, and thus configures how far
277
389
  # back in time a {Subscription#seek} can be done. Cannot be more than
278
390
  # 604,800 seconds (7 days) or less than 600 seconds (10 minutes).
279
391
  # Default is 604,800 seconds (7 days).
280
- # @param [String] endpoint A URL locating the endpoint to which messages
281
- # should be pushed.
282
- # @param [Hash] labels A hash of user-provided labels associated with
392
+ # @option options [String] endpoint A URL locating the endpoint to which messages
393
+ # should be pushed. The parameters `push_config` and `endpoint` should not both be provided.
394
+ # @option options [Google::Cloud::PubSub::Subscription::PushConfig] push_config
395
+ # The configuration for a push delivery endpoint that should contain the endpoint,
396
+ # and can contain authentication data (OIDC token authentication).
397
+ # The parameters `push_config` and `endpoint` should not both be provided.
398
+ # @option options [Hash] labels A hash of user-provided labels associated with
283
399
  # the subscription. You can use these to organize and group your
284
400
  # subscriptions. Label keys and values can be no longer than 63
285
401
  # characters, can only contain lowercase letters, numeric characters,
@@ -287,6 +403,31 @@ module Google
287
403
  # values are optional. Label keys must start with a letter and each
288
404
  # label in the list must have a different key. See [Creating and
289
405
  # Managing Labels](https://cloud.google.com/pubsub/docs/labels).
406
+ # @option options [Boolean] message_ordering Whether to enable message ordering
407
+ # on the subscription.
408
+ # @option options [String] filter An expression written in the Cloud Pub/Sub filter language.
409
+ # If non-empty, then only {Message} instances whose `attributes` field
410
+ # matches the filter are delivered on this subscription. If
411
+ # empty, then no messages are filtered out. Optional.
412
+ # @option options [Topic] dead_letter_topic
413
+ # The {Topic} to which dead letter messages for the subscription should be published.
414
+ # Dead lettering is done on a best effort basis. The same message might be dead lettered multiple
415
+ # times. The Cloud Pub/Sub service account associated with the enclosing subscription's parent project (i.e.,
416
+ # `service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have permission to Publish() to
417
+ # this topic.
418
+ #
419
+ # The operation will fail if the topic does not exist. Users should ensure that there is a subscription
420
+ # attached to this topic since messages published to a topic with no subscriptions are lost.
421
+ # @option options [Integer] dead_letter_max_delivery_attempts
422
+ # The maximum number of delivery attempts for any message in the subscription's dead letter policy.
423
+ # Dead lettering is done on a best effort basis. The same message might
424
+ # be dead lettered multiple times. The value must be between 5 and 100. If this parameter is 0, a default
425
+ # value of 5 is used. The `dead_letter_topic` must also be set.
426
+ # @option options [RetryPolicy] retry_policy
427
+ # A policy that specifies how Cloud Pub/Sub retries message delivery for this subscription.
428
+ # If not set, the default retry policy is applied. This generally implies that messages
429
+ # will be retried as soon as possible for healthy subscribers. Retry Policy will be triggered on NACKs or
430
+ # acknowledgement deadline exceeded events for a given message.
290
431
  #
291
432
  # @return [Google::Cloud::PubSub::Subscription]
292
433
  #
@@ -299,21 +440,74 @@ module Google
299
440
  # sub = topic.subscribe "my-topic-sub"
300
441
  # sub.name # => "my-topic-sub"
301
442
  #
302
- # @example Wait 2 minutes for acknowledgement and push all to endpoint:
443
+ # @example Wait 2 minutes for acknowledgement:
444
+ # require "google/cloud/pubsub"
445
+ #
446
+ # pubsub = Google::Cloud::PubSub.new
447
+ #
448
+ # topic = pubsub.topic "my-topic"
449
+ # sub = topic.subscribe "my-topic-sub",
450
+ # deadline: 120
451
+ #
452
+ # @example Configure a push endpoint:
303
453
  # require "google/cloud/pubsub"
304
454
  #
305
455
  # pubsub = Google::Cloud::PubSub.new
456
+ # topic = pubsub.topic "my-topic"
457
+ #
458
+ # push_config = Google::Cloud::PubSub::Subscription::PushConfig.new endpoint: "http://example.net/callback"
459
+ # push_config.set_oidc_token "service-account@example.net", "audience-header-value"
460
+ #
461
+ # sub = topic.subscribe "my-subscription", push_config: push_config
462
+ #
463
+ # @example Configure a Dead Letter Queues policy:
464
+ # require "google/cloud/pubsub"
465
+ #
466
+ # pubsub = Google::Cloud::PubSub.new
467
+ #
468
+ # # Dead Letter Queue (DLQ) testing requires IAM bindings to the Cloud Pub/Sub service account that is
469
+ # # automatically created and managed by the service team in a private project.
470
+ # my_project_number = "000000000000"
471
+ # service_account_email = "serviceAccount:service-#{my_project_number}@gcp-sa-pubsub.iam.gserviceaccount.com"
472
+ #
473
+ # dead_letter_topic = pubsub.topic "my-dead-letter-topic"
474
+ # dead_letter_subscription = dead_letter_topic.subscribe "my-dead-letter-sub"
475
+ #
476
+ # dead_letter_topic.policy { |p| p.add "roles/pubsub.publisher", service_account_email }
477
+ # dead_letter_subscription.policy { |p| p.add "roles/pubsub.subscriber", service_account_email }
306
478
  #
307
479
  # topic = pubsub.topic "my-topic"
308
480
  # sub = topic.subscribe "my-topic-sub",
309
- # deadline: 120,
310
- # endpoint: "https://example.com/push"
481
+ # dead_letter_topic: dead_letter_topic,
482
+ # dead_letter_max_delivery_attempts: 10
483
+ #
484
+ # @example Configure a Retry Policy:
485
+ # require "google/cloud/pubsub"
486
+ #
487
+ # pubsub = Google::Cloud::PubSub.new
488
+ #
489
+ # topic = pubsub.topic "my-topic"
311
490
  #
312
- def subscribe subscription_name, deadline: nil, retain_acked: false,
313
- retention: nil, endpoint: nil, labels: nil
491
+ # retry_policy = Google::Cloud::PubSub::RetryPolicy.new minimum_backoff: 5, maximum_backoff: 300
492
+ # sub = topic.subscribe "my-topic-sub", retry_policy: retry_policy
493
+ #
494
+ def subscribe subscription_name, **options
314
495
  ensure_service!
315
- options = { deadline: deadline, retain_acked: retain_acked,
316
- retention: retention, endpoint: endpoint, labels: labels }
496
+ if options[:push_config] && options[:endpoint]
497
+ raise ArgumentError, "endpoint and push_config were both provided. Please provide only one."
498
+ end
499
+ if options[:endpoint]
500
+ options[:push_config] =
501
+ Google::Cloud::PubSub::Subscription::PushConfig.new endpoint: options[:endpoint]
502
+ end
503
+
504
+ options[:dead_letter_topic_name] = options[:dead_letter_topic].name if options[:dead_letter_topic]
505
+ if options[:dead_letter_max_delivery_attempts] && !options[:dead_letter_topic_name]
506
+ # Service error message "3:Invalid resource name given (name=)." does not identify param.
507
+ raise ArgumentError, "dead_letter_topic is required with dead_letter_max_delivery_attempts"
508
+ end
509
+ options[:push_config] = options[:push_config].to_grpc if options[:push_config]
510
+ options[:retry_policy] = options[:retry_policy].to_grpc if options[:retry_policy]
317
511
  grpc = service.create_subscription name, subscription_name, options
318
512
  Subscription.from_grpc grpc, service
319
513
  end
@@ -323,7 +517,11 @@ module Google
323
517
  ##
324
518
  # Retrieves subscription by name.
325
519
  #
326
- # @param [String] subscription_name Name of a subscription.
520
+ # @param [String] subscription_name Name of a subscription. The value
521
+ # can be a simple subscription ID (relative name), in which case the
522
+ # current project ID will be supplied, or a fully-qualified
523
+ # subscription name in the form
524
+ # `projects/{project_id}/subscriptions/{subscription_id}`.
327
525
  # @param [Boolean] skip_lookup Optionally create a {Subscription} object
328
526
  # without verifying the subscription resource exists on the Pub/Sub
329
527
  # service. Calls made on this object will raise errors if the service
@@ -355,9 +553,7 @@ module Google
355
553
  #
356
554
  def subscription subscription_name, skip_lookup: nil
357
555
  ensure_service!
358
- if skip_lookup
359
- return Subscription.from_name subscription_name, service
360
- end
556
+ return Subscription.from_name subscription_name, service if skip_lookup
361
557
  grpc = service.get_subscription subscription_name
362
558
  Subscription.from_grpc grpc, service
363
559
  rescue Google::Cloud::NotFoundError
@@ -416,6 +612,8 @@ module Google
416
612
  # @param [String, File] data The message payload. This will be converted
417
613
  # to bytes encoded as ASCII-8BIT.
418
614
  # @param [Hash] attributes Optional attributes for the message.
615
+ # @param [String] ordering_key Identifies related messages for which
616
+ # publish order should be respected.
419
617
  # @yield [batch] a block for publishing multiple messages in one
420
618
  # request
421
619
  # @yieldparam [BatchPublisher] batch the topic batch publisher
@@ -464,26 +662,90 @@ module Google
464
662
  # t.publish "task 3 completed", foo: :bif
465
663
  # end
466
664
  #
467
- def publish data = nil, attributes = {}
665
+ # @example Ordered messages are supported using ordering_key:
666
+ # require "google/cloud/pubsub"
667
+ #
668
+ # pubsub = Google::Cloud::PubSub.new
669
+ #
670
+ # topic = pubsub.topic "my-ordered-topic"
671
+ #
672
+ # # Ensure that message ordering is enabled.
673
+ # topic.enable_message_ordering!
674
+ #
675
+ # # Publish an ordered message with an ordering key.
676
+ # topic.publish "task completed",
677
+ # ordering_key: "task-key"
678
+ #
679
+ def publish data = nil, attributes = nil, ordering_key: nil, compress: nil, compression_bytes_threshold: nil,
680
+ **extra_attrs, &block
468
681
  ensure_service!
469
- batch = BatchPublisher.new data, attributes
470
- yield batch if block_given?
682
+ batch = BatchPublisher.new data,
683
+ attributes,
684
+ ordering_key,
685
+ extra_attrs,
686
+ compress: compress,
687
+ compression_bytes_threshold: compression_bytes_threshold
688
+
689
+ block&.call batch
471
690
  return nil if batch.messages.count.zero?
472
- publish_batch_messages batch
691
+ batch.publish_batch_messages name, service
473
692
  end
474
693
 
475
694
  ##
476
- # Publishes a message asynchronously to the topic.
695
+ # Publishes a message asynchronously to the topic using
696
+ # {#async_publisher}.
477
697
  #
478
698
  # The message payload must not be empty; it must contain either a
479
699
  # non-empty data field, or at least one attribute.
480
700
  #
701
+ # Google Cloud Pub/Sub ordering keys provide the ability to ensure
702
+ # related messages are sent to subscribers in the order in which they
703
+ # were published. Messages can be tagged with an ordering key, a string
704
+ # that identifies related messages for which publish order should be
705
+ # respected. The service guarantees that, for a given ordering key and
706
+ # publisher, messages are sent to subscribers in the order in which they
707
+ # were published. Ordering does not require sacrificing high throughput
708
+ # or scalability, as the service automatically distributes messages for
709
+ # different ordering keys across subscribers.
710
+ #
711
+ # To use ordering keys, specify `ordering_key`. Before specifying
712
+ # `ordering_key` on a message a call to `#enable_message_ordering!` must
713
+ # be made or an error will be raised.
714
+ #
715
+ # @note At the time of this release, ordering keys are not yet publicly
716
+ # enabled and requires special project enablements.
717
+ #
718
+ # Publisher flow control limits the number of outstanding messages that
719
+ # are allowed to wait to be published. See the `flow_control` key in the
720
+ # `async` parameter in {Project#topic} for more information about publisher
721
+ # flow control settings.
722
+ #
481
723
  # @param [String, File] data The message payload. This will be converted
482
724
  # to bytes encoded as ASCII-8BIT.
483
725
  # @param [Hash] attributes Optional attributes for the message.
726
+ # @param [String] ordering_key Identifies related messages for which
727
+ # publish order should be respected.
484
728
  # @yield [result] the callback for when the message has been published
485
729
  # @yieldparam [PublishResult] result the result of the asynchronous
486
730
  # publish
731
+ # @raise [Google::Cloud::PubSub::AsyncPublisherStopped] when the
732
+ # publisher is stopped. (See {AsyncPublisher#stop} and
733
+ # {AsyncPublisher#stopped?}.)
734
+ # @raise [Google::Cloud::PubSub::OrderedMessagesDisabled] when
735
+ # publishing a message with an `ordering_key` but ordered messages are
736
+ # not enabled. (See {#message_ordering?} and
737
+ # {#enable_message_ordering!}.)
738
+ # @raise [Google::Cloud::PubSub::OrderingKeyError] when publishing a
739
+ # message with an `ordering_key` that has already failed when
740
+ # publishing. Use {#resume_publish} to allow this `ordering_key` to be
741
+ # published again.
742
+ # @raise [Google::Cloud::PubSub::FlowControlLimitError] when publish flow
743
+ # control limits are exceeded, and the `async` parameter key
744
+ # `flow_control.limit_exceeded_behavior` is set to `:error` or `:block`.
745
+ # If `flow_control.limit_exceeded_behavior` is set to `:block`, this error
746
+ # will be raised only when a limit would be exceeded by a single message.
747
+ # See the `async` parameter in {Project#topic} for more information about
748
+ # `flow_control` settings.
487
749
  #
488
750
  # @example
489
751
  # require "google/cloud/pubsub"
@@ -499,7 +761,8 @@ module Google
499
761
  # end
500
762
  # end
501
763
  #
502
- # topic.async_publisher.stop.wait!
764
+ # # Shut down the publisher when ready to stop publishing messages.
765
+ # topic.async_publisher.stop!
503
766
  #
504
767
  # @example A message can be published using a File object:
505
768
  # require "google/cloud/pubsub"
@@ -510,7 +773,8 @@ module Google
510
773
  # file = File.open "message.txt", mode: "rb"
511
774
  # topic.publish_async file
512
775
  #
513
- # topic.async_publisher.stop.wait!
776
+ # # Shut down the publisher when ready to stop publishing messages.
777
+ # topic.async_publisher.stop!
514
778
  #
515
779
  # @example Additionally, a message can be published with attributes:
516
780
  # require "google/cloud/pubsub"
@@ -521,13 +785,76 @@ module Google
521
785
  # topic.publish_async "task completed",
522
786
  # foo: :bar, this: :that
523
787
  #
524
- # topic.async_publisher.stop.wait!
788
+ # # Shut down the publisher when ready to stop publishing messages.
789
+ # topic.async_publisher.stop!
790
+ #
791
+ # @example Ordered messages are supported using ordering_key:
792
+ # require "google/cloud/pubsub"
793
+ #
794
+ # pubsub = Google::Cloud::PubSub.new
795
+ #
796
+ # topic = pubsub.topic "my-ordered-topic"
797
+ #
798
+ # # Ensure that message ordering is enabled.
799
+ # topic.enable_message_ordering!
525
800
  #
526
- def publish_async data = nil, attributes = {}, &block
801
+ # # Publish an ordered message with an ordering key.
802
+ # topic.publish_async "task completed",
803
+ # ordering_key: "task-key"
804
+ #
805
+ # # Shut down the publisher when ready to stop publishing messages.
806
+ # topic.async_publisher.stop!
807
+ #
808
+ def publish_async data = nil, attributes = nil, ordering_key: nil, **extra_attrs, &callback
527
809
  ensure_service!
528
810
 
529
- @async_publisher ||= AsyncPublisher.new name, service, @async_opts
530
- @async_publisher.publish data, attributes, &block
811
+ @async_publisher ||= AsyncPublisher.new name, service, **@async_opts
812
+ @async_publisher.publish data, attributes, ordering_key: ordering_key, **extra_attrs, &callback
813
+ end
814
+
815
+ ##
816
+ # Enables message ordering for messages with ordering keys on the
817
+ # {#async_publisher}. When enabled, messages published with the same
818
+ # `ordering_key` will be delivered in the order they were published.
819
+ #
820
+ # @note At the time of this release, ordering keys are not yet publicly
821
+ # enabled and requires special project enablements.
822
+ #
823
+ # See {#message_ordering?}. See {#publish_async},
824
+ # {Subscription#listen}, and {Message#ordering_key}.
825
+ #
826
+ def enable_message_ordering!
827
+ @async_publisher ||= AsyncPublisher.new name, service, **@async_opts
828
+ @async_publisher.enable_message_ordering!
829
+ end
830
+
831
+ ##
832
+ # Whether message ordering for messages with ordering keys has been
833
+ # enabled on the {#async_publisher}. When enabled, messages published
834
+ # with the same `ordering_key` will be delivered in the order they were
835
+ # published. When disabled, messages may be delivered in any order.
836
+ #
837
+ # See {#enable_message_ordering!}. See {#publish_async},
838
+ # {Subscription#listen}, and {Message#ordering_key}.
839
+ #
840
+ # @return [Boolean]
841
+ #
842
+ def message_ordering?
843
+ @async_publisher ||= AsyncPublisher.new name, service, **@async_opts
844
+ @async_publisher.message_ordering?
845
+ end
846
+
847
+ ##
848
+ # Resume publishing ordered messages for the provided ordering key.
849
+ #
850
+ # @param [String] ordering_key Identifies related messages for which
851
+ # publish order should be respected.
852
+ #
853
+ # @return [boolean] `true` when resumed, `false` otherwise.
854
+ #
855
+ def resume_publish ordering_key
856
+ @async_publisher ||= AsyncPublisher.new name, service, **@async_opts
857
+ @async_publisher.resume_publish ordering_key
531
858
  end
532
859
 
533
860
  ##
@@ -745,7 +1072,7 @@ module Google
745
1072
  # @private New reference {Topic} object without making an HTTP request.
746
1073
  def self.from_name name, service, options = {}
747
1074
  name = service.topic_path name, options
748
- from_grpc(nil, service).tap do |t|
1075
+ from_grpc(nil, service, async: options[:async]).tap do |t|
749
1076
  t.instance_variable_set :@resource_name, name
750
1077
  end
751
1078
  end
@@ -765,13 +1092,6 @@ module Google
765
1092
  ensure_service!
766
1093
  reload! if reference?
767
1094
  end
768
-
769
- ##
770
- # Call the publish API with arrays of data data and attrs.
771
- def publish_batch_messages batch
772
- grpc = service.publish name, batch.messages
773
- batch.to_gcloud_messages Array(grpc.message_ids)
774
- end
775
1095
  end
776
1096
  end
777
1097
 
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module PubSub
19
- VERSION = "1.0.2".freeze
19
+ VERSION = "2.19.0".freeze
20
20
  end
21
21
 
22
22
  Pubsub = PubSub unless const_defined? :Pubsub