google-cloud-pubsub 1.0.2 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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