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
@@ -18,78 +18,94 @@ require "google/cloud/pubsub/credentials"
18
18
  require "google/cloud/pubsub/convert"
19
19
  require "google/cloud/pubsub/version"
20
20
  require "google/cloud/pubsub/v1"
21
- require "google/gax/errors"
21
+ require "securerandom"
22
22
 
23
23
  module Google
24
24
  module Cloud
25
25
  module PubSub
26
26
  ##
27
- # @private Represents the GAX Pub/Sub service, including all the API
28
- # methods.
27
+ # @private Represents the Pub/Sub service API, including IAM mixins.
29
28
  class Service
30
- attr_accessor :project, :credentials, :host, :timeout, :client_config
29
+ attr_accessor :project
30
+ attr_accessor :credentials
31
+ attr_accessor :host
32
+ attr_accessor :timeout
33
+ ###
34
+ # The same client_id is used across all streaming pull connections that are created by this client. This is
35
+ # intentional, as it indicates to the server that any guarantees, such as message ordering, made for a stream
36
+ # that is disconnected will be made for the stream that is created to replace it. The attr_accessor allows the
37
+ # value to be replaced for unit testing.
38
+ attr_accessor :client_id
39
+
40
+ attr_reader :universe_domain
31
41
 
32
42
  ##
33
43
  # Creates a new Service instance.
34
- def initialize project, credentials, host: nil, timeout: nil,
35
- client_config: nil
44
+ def initialize project, credentials, host: nil, timeout: nil, universe_domain: nil
36
45
  @project = project
37
46
  @credentials = credentials
38
- @host = host || V1::PublisherClient::SERVICE_ADDRESS
47
+ @host = host
39
48
  @timeout = timeout
40
- @client_config = client_config || {}
41
- end
42
-
43
- def channel
44
- require "grpc"
45
- GRPC::Core::Channel.new host, chan_args, chan_creds
46
- end
47
-
48
- def chan_args
49
- { "grpc.max_send_message_length" => -1,
50
- "grpc.max_receive_message_length" => -1,
51
- "grpc.keepalive_time_ms" => 300000,
52
- "grpc.service_config_disable_resolution" => 1 }
53
- end
54
-
55
- def chan_creds
56
- return credentials if insecure?
57
- require "grpc"
58
- GRPC::Core::ChannelCredentials.new.compose \
59
- GRPC::Core::CallCredentials.new credentials.client.updater_proc
49
+ @client_id = SecureRandom.uuid.freeze
50
+ @universe_domain = universe_domain || ENV["GOOGLE_CLOUD_UNIVERSE_DOMAIN"] || "googleapis.com"
60
51
  end
61
52
 
62
53
  def subscriber
63
54
  return mocked_subscriber if mocked_subscriber
64
- @subscriber ||= begin
65
- V1::SubscriberClient.new(
66
- credentials: channel,
67
- timeout: timeout,
68
- client_config: client_config,
69
- lib_name: "gccl",
70
- lib_version: Google::Cloud::PubSub::VERSION
71
- )
55
+ @subscriber ||= V1::Subscriber::Client.new do |config|
56
+ config.credentials = credentials if credentials
57
+ override_client_config_timeouts config if timeout
58
+ config.endpoint = host if host
59
+ config.universe_domain = universe_domain
60
+ config.lib_name = "gccl"
61
+ config.lib_version = Google::Cloud::PubSub::VERSION
62
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
72
63
  end
73
64
  end
74
65
  attr_accessor :mocked_subscriber
75
66
 
76
67
  def publisher
77
68
  return mocked_publisher if mocked_publisher
78
- @publisher ||= begin
79
- V1::PublisherClient.new(
80
- credentials: channel,
81
- timeout: timeout,
82
- client_config: client_config,
83
- lib_name: "gccl",
84
- lib_version: Google::Cloud::PubSub::VERSION
85
- )
69
+ @publisher ||= V1::Publisher::Client.new do |config|
70
+ config.credentials = credentials if credentials
71
+ override_client_config_timeouts config if timeout
72
+ config.endpoint = host if host
73
+ config.universe_domain = universe_domain
74
+ config.lib_name = "gccl"
75
+ config.lib_version = Google::Cloud::PubSub::VERSION
76
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
86
77
  end
87
78
  end
88
79
  attr_accessor :mocked_publisher
89
80
 
90
- def insecure?
91
- credentials == :this_channel_is_insecure
81
+ def iam
82
+ return mocked_iam if mocked_iam
83
+ @iam ||= begin
84
+ iam = (@publisher || @subscriber || @schemas || subscriber).iam_policy_client
85
+ iam.configure do |config|
86
+ override_client_config_timeouts config if timeout
87
+ config.lib_name = "gccl"
88
+ config.lib_version = Google::Cloud::PubSub::VERSION
89
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
90
+ end
91
+ iam
92
+ end
93
+ end
94
+ attr_accessor :mocked_iam
95
+
96
+ def schemas
97
+ return mocked_schemas if mocked_schemas
98
+ @schemas ||= V1::SchemaService::Client.new do |config|
99
+ config.credentials = credentials if credentials
100
+ override_client_config_timeouts config if timeout
101
+ config.endpoint = host if host
102
+ config.universe_domain = universe_domain
103
+ config.lib_name = "gccl"
104
+ config.lib_version = Google::Cloud::PubSub::VERSION
105
+ config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
106
+ end
92
107
  end
108
+ attr_accessor :mocked_schemas
93
109
 
94
110
  ##
95
111
  # Gets the configuration of a topic.
@@ -98,58 +114,59 @@ module Google
98
114
  # If other attributes are added in the future,
99
115
  # they will be returned here.
100
116
  def get_topic topic_name, options = {}
101
- execute do
102
- publisher.get_topic topic_path(topic_name, options),
103
- options: default_options
104
- end
117
+ publisher.get_topic topic: topic_path(topic_name, options)
105
118
  end
106
119
 
107
120
  ##
108
121
  # Lists matching topics.
109
122
  def list_topics options = {}
110
- call_options = default_options
111
- if (token = options[:token])
112
- call_options = Google::Gax::CallOptions.new(
113
- kwargs: default_headers,
114
- page_token: token
115
- )
116
- end
123
+ paged_enum = publisher.list_topics project: project_path(options),
124
+ page_size: options[:max],
125
+ page_token: options[:token]
117
126
 
118
- execute do
119
- paged_enum = publisher.list_topics project_path(options),
120
- page_size: options[:max],
121
- options: call_options
122
-
123
- paged_enum.page.response
124
- end
127
+ paged_enum.response
125
128
  end
126
129
 
127
130
  ##
128
131
  # Creates the given topic with the given name.
129
- def create_topic topic_name, labels: nil, kms_key_name: nil,
130
- persistence_regions: nil, options: {}
132
+ def create_topic topic_name,
133
+ labels: nil,
134
+ kms_key_name: nil,
135
+ persistence_regions: nil,
136
+ schema_name: nil,
137
+ message_encoding: nil,
138
+ retention: nil,
139
+ ingestion_data_source_settings: nil,
140
+ options: {}
131
141
  if persistence_regions
132
- message_storage_policy = {
142
+ message_storage_policy = Google::Cloud::PubSub::V1::MessageStoragePolicy.new(
133
143
  allowed_persistence_regions: Array(persistence_regions)
134
- }
144
+ )
135
145
  end
136
146
 
137
- execute do
138
- publisher.create_topic \
139
- topic_path(topic_name, options),
140
- labels: labels,
141
- kms_key_name: kms_key_name,
142
- message_storage_policy: message_storage_policy,
143
- options: default_options
147
+ if schema_name || message_encoding
148
+ unless schema_name && message_encoding
149
+ raise ArgumentError, "Schema settings must include both schema_name and message_encoding."
150
+ end
151
+ schema_settings = Google::Cloud::PubSub::V1::SchemaSettings.new(
152
+ schema: schema_path(schema_name),
153
+ encoding: message_encoding.to_s.upcase
154
+ )
144
155
  end
156
+
157
+ publisher.create_topic \
158
+ name: topic_path(topic_name, options),
159
+ labels: labels,
160
+ kms_key_name: kms_key_name,
161
+ message_storage_policy: message_storage_policy,
162
+ schema_settings: schema_settings,
163
+ message_retention_duration: Convert.number_to_duration(retention),
164
+ ingestion_data_source_settings: ingestion_data_source_settings
145
165
  end
146
166
 
147
167
  def update_topic topic_obj, *fields
148
168
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
149
- execute do
150
- publisher.update_topic \
151
- topic_obj, mask, options: default_options
152
- end
169
+ publisher.update_topic topic: topic_obj, update_mask: mask
153
170
  end
154
171
 
155
172
  ##
@@ -158,10 +175,7 @@ module Google
158
175
  # exist. After a topic is deleted, a new topic may be created with the
159
176
  # same name.
160
177
  def delete_topic topic_name
161
- execute do
162
- publisher.delete_topic topic_path(topic_name),
163
- options: default_options
164
- end
178
+ publisher.delete_topic topic: topic_path(topic_name)
165
179
  end
166
180
 
167
181
  ##
@@ -169,284 +183,253 @@ module Google
169
183
  # Raises GRPC status code 5 if the topic does not exist.
170
184
  # The messages parameter is an array of arrays.
171
185
  # The first element is the data, second is attributes hash.
172
- def publish topic, messages
173
- execute do
174
- publisher.publish topic_path(topic), messages,
175
- options: default_options
176
- end
186
+ def publish topic, messages, compress: false
187
+ request = { topic: topic_path(topic), messages: messages }
188
+ compress_options = ::Gapic::CallOptions.new metadata: { "grpc-internal-encoding-request": "gzip" }
189
+ compress ? (publisher.publish request, compress_options) : (publisher.publish request)
177
190
  end
178
191
 
179
192
  ##
180
193
  # Gets the details of a subscription.
181
194
  def get_subscription subscription_name, options = {}
182
- subscription = subscription_path subscription_name, options
183
- execute do
184
- subscriber.get_subscription subscription, options: default_options
185
- end
195
+ subscriber.get_subscription subscription: subscription_path(subscription_name, options)
186
196
  end
187
197
 
188
198
  ##
189
199
  # Lists matching subscriptions by project and topic.
190
200
  def list_topics_subscriptions topic, options = {}
191
- call_options = default_options
192
- if (token = options[:token])
193
- call_options = Google::Gax::CallOptions.new(
194
- kwargs: default_headers,
195
- page_token: token
196
- )
197
- end
198
-
199
- execute do
200
- paged_enum = publisher.list_topic_subscriptions \
201
- topic_path(topic, options),
202
- page_size: options[:max],
203
- options: call_options
204
-
205
- paged_enum.page.response
206
- end
201
+ publisher.list_topic_subscriptions topic: topic_path(topic, options),
202
+ page_size: options[:max],
203
+ page_token: options[:token]
207
204
  end
208
205
 
209
206
  ##
210
207
  # Lists matching subscriptions by project.
211
208
  def list_subscriptions options = {}
212
- call_options = default_options
213
- if (token = options[:token])
214
- call_options = Google::Gax::CallOptions.new(
215
- kwargs: default_headers,
216
- page_token: token
217
- )
218
- end
219
-
220
- execute do
221
- paged_enum = subscriber.list_subscriptions project_path(options),
222
- page_size: options[:max],
223
- options: call_options
209
+ paged_enum = subscriber.list_subscriptions project: project_path(options),
210
+ page_size: options[:max],
211
+ page_token: options[:token]
224
212
 
225
- paged_enum.page.response
226
- end
213
+ paged_enum.response
227
214
  end
228
215
 
229
216
  ##
230
217
  # Creates a subscription on a given topic for a given subscriber.
231
218
  def create_subscription topic, subscription_name, options = {}
232
- name = subscription_path subscription_name, options
233
- topic = topic_path topic
234
- push_config = if options[:endpoint]
235
- Google::Cloud::PubSub::V1::PushConfig.new \
236
- push_endpoint: options[:endpoint],
237
- attributes: (options[:attributes] || {}).to_h
238
- end
239
- deadline = options[:deadline]
240
- retain_acked = options[:retain_acked]
241
- mrd = Convert.number_to_duration options[:retention]
242
- labels = options[:labels]
243
-
244
- execute do
245
- subscriber.create_subscription \
246
- name, topic,
247
- push_config: push_config,
248
- ack_deadline_seconds: deadline,
249
- retain_acked_messages: retain_acked,
250
- message_retention_duration: mrd,
251
- labels: labels,
252
- options: default_options
253
- end
219
+ updated_option = construct_create_subscription_options topic, subscription_name, options
220
+ subscriber.create_subscription(**updated_option)
254
221
  end
255
222
 
256
223
  def update_subscription subscription_obj, *fields
257
224
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
258
- execute do
259
- subscriber.update_subscription \
260
- subscription_obj, mask, options: default_options
261
- end
225
+ subscriber.update_subscription subscription: subscription_obj, update_mask: mask
262
226
  end
263
227
 
264
228
  ##
265
- # Deletes an existing subscription.
266
- # All pending messages in the subscription are immediately dropped.
229
+ # Deletes an existing subscription. All pending messages in the subscription are immediately dropped.
267
230
  def delete_subscription subscription
268
- execute do
269
- subscriber.delete_subscription subscription_path(subscription),
270
- options: default_options
271
- end
231
+ subscriber.delete_subscription subscription: subscription_path(subscription)
232
+ end
233
+
234
+ ##
235
+ # Detaches a subscription from its topic. All messages retained in the subscription are dropped. Subsequent
236
+ # `Pull` and `StreamingPull` requests will raise `FAILED_PRECONDITION`. If the subscription is a push
237
+ # subscription, pushes to the endpoint will stop.
238
+ def detach_subscription subscription
239
+ publisher.detach_subscription subscription: subscription_path(subscription)
272
240
  end
273
241
 
274
242
  ##
275
243
  # Pulls a single message from the server.
276
244
  def pull subscription, options = {}
277
- subscription = subscription_path subscription, options
278
245
  max_messages = options.fetch(:max, 100).to_i
279
246
  return_immediately = !(!options.fetch(:immediate, true))
280
247
 
281
- execute do
282
- subscriber.pull subscription,
283
- max_messages,
284
- return_immediately: return_immediately,
285
- options: default_options
286
- end
248
+ subscriber.pull subscription: subscription_path(subscription, options),
249
+ max_messages: max_messages,
250
+ return_immediately: return_immediately
287
251
  end
288
252
 
289
- def streaming_pull request_enum
290
- execute do
291
- subscriber.streaming_pull request_enum, options: default_options
292
- end
253
+ def streaming_pull request_enum, options = {}
254
+ subscriber.streaming_pull request_enum, options
293
255
  end
294
256
 
295
257
  ##
296
258
  # Acknowledges receipt of a message.
297
259
  def acknowledge subscription, *ack_ids
298
- execute do
299
- subscriber.acknowledge subscription_path(subscription), ack_ids,
300
- options: default_options
301
- end
260
+ subscriber.acknowledge subscription: subscription_path(subscription), ack_ids: ack_ids
302
261
  end
303
262
 
304
263
  ##
305
264
  # Modifies the PushConfig for a specified subscription.
306
265
  def modify_push_config subscription, endpoint, attributes
307
- subscription = subscription_path subscription
308
266
  # Convert attributes to strings to match the protobuf definition
309
- attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
267
+ attributes = attributes.to_h { |k, v| [String(k), String(v)] }
310
268
  push_config = Google::Cloud::PubSub::V1::PushConfig.new(
311
269
  push_endpoint: endpoint,
312
270
  attributes: attributes
313
271
  )
314
272
 
315
- execute do
316
- subscriber.modify_push_config subscription, push_config,
317
- options: default_options
318
- end
273
+ subscriber.modify_push_config subscription: subscription_path(subscription),
274
+ push_config: push_config
319
275
  end
320
276
 
321
277
  ##
322
278
  # Modifies the ack deadline for a specific message.
323
279
  def modify_ack_deadline subscription, ids, deadline
324
- execute do
325
- subscriber.modify_ack_deadline subscription_path(subscription),
326
- Array(ids),
327
- deadline, options: default_options
328
- end
280
+ subscriber.modify_ack_deadline subscription: subscription_path(subscription),
281
+ ack_ids: Array(ids),
282
+ ack_deadline_seconds: deadline
329
283
  end
330
284
 
331
285
  ##
332
286
  # Lists snapshots by project.
333
287
  def list_snapshots options = {}
334
- call_options = default_options
335
- if (token = options[:token])
336
- call_options = Google::Gax::CallOptions.new(
337
- kwargs: default_headers,
338
- page_token: token
339
- )
340
- end
341
-
342
- execute do
343
- paged_enum = subscriber.list_snapshots project_path(options),
344
- page_size: options[:max],
345
- options: call_options
288
+ paged_enum = subscriber.list_snapshots project: project_path(options),
289
+ page_size: options[:max],
290
+ page_token: options[:token]
346
291
 
347
- paged_enum.page.response
348
- end
292
+ paged_enum.response
349
293
  end
350
294
 
351
295
  ##
352
296
  # Creates a snapshot on a given subscription.
353
297
  def create_snapshot subscription, snapshot_name, labels: nil
354
- name = snapshot_path snapshot_name
355
- execute do
356
- subscriber.create_snapshot name,
357
- subscription_path(subscription),
358
- labels: labels,
359
- options: default_options
360
- end
298
+ subscriber.create_snapshot name: snapshot_path(snapshot_name),
299
+ subscription: subscription_path(subscription),
300
+ labels: labels
361
301
  end
362
302
 
363
303
  def update_snapshot snapshot_obj, *fields
364
304
  mask = Google::Protobuf::FieldMask.new paths: fields.map(&:to_s)
365
- execute do
366
- subscriber.update_snapshot \
367
- snapshot_obj, mask, options: default_options
368
- end
305
+ subscriber.update_snapshot snapshot: snapshot_obj, update_mask: mask
369
306
  end
370
307
 
371
308
  ##
372
309
  # Deletes an existing snapshot.
373
310
  # All pending messages in the snapshot are immediately dropped.
374
311
  def delete_snapshot snapshot
375
- execute do
376
- subscriber.delete_snapshot snapshot_path(snapshot),
377
- options: default_options
378
- end
312
+ subscriber.delete_snapshot snapshot: snapshot_path(snapshot)
379
313
  end
380
314
 
381
315
  ##
382
316
  # Adjusts the given subscription to a time or snapshot.
383
317
  def seek subscription, time_or_snapshot
384
- subscription = subscription_path subscription
385
- execute do
386
- if a_time? time_or_snapshot
387
- time = Convert.time_to_timestamp time_or_snapshot
388
- subscriber.seek subscription, time: time, options: default_options
389
- else
390
- if time_or_snapshot.is_a? Snapshot
391
- time_or_snapshot = time_or_snapshot.name
392
- end
393
- subscriber.seek subscription,
394
- snapshot: snapshot_path(time_or_snapshot),
395
- options: default_options
396
- end
318
+ if a_time? time_or_snapshot
319
+ time = Convert.time_to_timestamp time_or_snapshot
320
+ subscriber.seek subscription: subscription, time: time
321
+ else
322
+ time_or_snapshot = time_or_snapshot.name if time_or_snapshot.is_a? Snapshot
323
+ subscriber.seek subscription: subscription_path(subscription),
324
+ snapshot: snapshot_path(time_or_snapshot)
397
325
  end
398
326
  end
399
327
 
400
- def get_topic_policy topic_name, options = {}
401
- execute do
402
- publisher.get_iam_policy topic_path(topic_name, options),
403
- options: default_options
404
- end
328
+ ##
329
+ # Lists schemas in the current (or given) project.
330
+ # @param view [String, Symbol, nil] Possible values:
331
+ # * `BASIC` - Include the name and type of the schema, but not the definition.
332
+ # * `FULL` - Include all Schema object fields.
333
+ #
334
+ def list_schemas view, options = {}
335
+ schema_view = Google::Cloud::PubSub::V1::SchemaView.const_get view.to_s.upcase
336
+ paged_enum = schemas.list_schemas parent: project_path(options),
337
+ view: schema_view,
338
+ page_size: options[:max],
339
+ page_token: options[:token]
340
+
341
+ paged_enum.response
405
342
  end
406
343
 
407
- def set_topic_policy topic_name, new_policy, options = {}
408
- resource = topic_path topic_name, options
344
+ ##
345
+ # Creates a schema in the current (or given) project.
346
+ def create_schema schema_id, type, definition, options = {}
347
+ schema = Google::Cloud::PubSub::V1::Schema.new(
348
+ type: type,
349
+ definition: definition
350
+ )
351
+ schemas.create_schema parent: project_path(options),
352
+ schema: schema,
353
+ schema_id: schema_id
354
+ end
409
355
 
410
- execute do
411
- publisher.set_iam_policy resource, new_policy,
412
- options: default_options
413
- end
356
+ ##
357
+ # Gets the details of a schema.
358
+ # @param view [String, Symbol, nil] The set of fields to return in the response. Possible values:
359
+ # * `BASIC` - Include the name and type of the schema, but not the definition.
360
+ # * `FULL` - Include all Schema object fields.
361
+ #
362
+ def get_schema schema_name, view, options = {}
363
+ schema_view = Google::Cloud::PubSub::V1::SchemaView.const_get view.to_s.upcase
364
+ schemas.get_schema name: schema_path(schema_name, options),
365
+ view: schema_view
414
366
  end
415
367
 
416
- def test_topic_permissions topic_name, permissions, options = {}
417
- resource = topic_path topic_name, options
368
+ ##
369
+ # Delete a schema.
370
+ def delete_schema schema_name
371
+ schemas.delete_schema name: schema_path(schema_name)
372
+ end
418
373
 
419
- execute do
420
- publisher.test_iam_permissions resource, permissions,
421
- options: default_options
374
+ ##
375
+ # Validate the definition string intended for a schema.
376
+ def validate_schema type, definition, options = {}
377
+ schema = Google::Cloud::PubSub::V1::Schema.new(
378
+ type: type,
379
+ definition: definition
380
+ )
381
+ schemas.validate_schema parent: project_path(options),
382
+ schema: schema
383
+ end
384
+
385
+ ##
386
+ # Validates a message against a schema.
387
+ #
388
+ # @param message_data [String] Message to validate against the provided `schema_spec`.
389
+ # @param message_encoding [Google::Cloud::PubSub::V1::Encoding] The encoding expected for messages.
390
+ # @param schema_name [String] Name of the schema against which to validate.
391
+ # @param project [String] Name of the project if not the default project.
392
+ # @param type [String] Ad-hoc schema type against which to validate.
393
+ # @param definition [String] Ad-hoc schema definition against which to validate.
394
+ #
395
+ def validate_message message_data, message_encoding, schema_name: nil, project: nil, type: nil, definition: nil
396
+ if type && definition
397
+ schema = Google::Cloud::PubSub::V1::Schema.new(
398
+ type: type,
399
+ definition: definition
400
+ )
422
401
  end
402
+ schemas.validate_message parent: project_path(project: project),
403
+ name: schema_path(schema_name),
404
+ schema: schema,
405
+ message: message_data,
406
+ encoding: message_encoding
423
407
  end
424
408
 
425
- def get_subscription_policy subscription_name, options = {}
426
- resource = subscription_path subscription_name, options
409
+ # Helper methods
427
410
 
428
- execute do
429
- subscriber.get_iam_policy resource, options: default_options
430
- end
411
+ def get_topic_policy topic_name, options = {}
412
+ iam.get_iam_policy resource: topic_path(topic_name, options)
431
413
  end
432
414
 
433
- def set_subscription_policy subscription_name, new_policy, options = {}
434
- resource = subscription_path subscription_name, options
415
+ def set_topic_policy topic_name, new_policy, options = {}
416
+ iam.set_iam_policy resource: topic_path(topic_name, options), policy: new_policy
417
+ end
435
418
 
436
- execute do
437
- subscriber.set_iam_policy resource, new_policy,
438
- options: default_options
439
- end
419
+ def test_topic_permissions topic_name, permissions, options = {}
420
+ iam.test_iam_permissions resource: topic_path(topic_name, options), permissions: permissions
440
421
  end
441
422
 
442
- def test_subscription_permissions subscription_name,
443
- permissions, options = {}
444
- resource = subscription_path subscription_name, options
423
+ def get_subscription_policy subscription_name, options = {}
424
+ iam.get_iam_policy resource: subscription_path(subscription_name, options)
425
+ end
445
426
 
446
- execute do
447
- subscriber.test_iam_permissions resource, permissions,
448
- options: default_options
449
- end
427
+ def set_subscription_policy subscription_name, new_policy, options = {}
428
+ iam.set_iam_policy resource: subscription_path(subscription_name, options), policy: new_policy
429
+ end
430
+
431
+ def test_subscription_permissions subscription_name, permissions, options = {}
432
+ iam.test_iam_permissions resource: subscription_path(subscription_name, options), permissions: permissions
450
433
  end
451
434
 
452
435
  def project_path options = {}
@@ -465,18 +448,33 @@ module Google
465
448
  end
466
449
 
467
450
  def snapshot_path snapshot_name, options = {}
468
- if snapshot_name.nil? || snapshot_name.to_s.include?("/")
469
- return snapshot_name
470
- end
451
+ return snapshot_name if snapshot_name.nil? || snapshot_name.to_s.include?("/")
471
452
  "#{project_path options}/snapshots/#{snapshot_name}"
472
453
  end
473
454
 
455
+ def schema_path schema_name, options = {}
456
+ return schema_name if schema_name.nil? || schema_name.to_s.include?("/")
457
+ "#{project_path options}/schemas/#{schema_name}"
458
+ end
459
+
474
460
  def inspect
475
- "#<#{self.class.name} #{@project}>"
461
+ "#<#{self.class.name} (#{@project})>"
476
462
  end
477
463
 
478
464
  protected
479
465
 
466
+ # Set the timeout in the client config.
467
+ # Override the default timeout in each individual RPC config as well, since when they are non-nil, these
468
+ # defaults have precedence over the top-level config.timeout. See Gapic::CallOptions#apply_defaults.
469
+ def override_client_config_timeouts config
470
+ config.timeout = timeout
471
+ rpc_names = config.rpcs.methods - Object.methods
472
+ rpc_names.each do |rpc_name|
473
+ rpc = config.rpcs.send rpc_name
474
+ rpc.timeout = timeout if rpc.respond_to? :timeout=
475
+ end
476
+ end
477
+
480
478
  def a_time? obj
481
479
  return false unless obj.respond_to? :to_time
482
480
  # Rails' String#to_time returns nil if the string doesn't parse.
@@ -484,19 +482,37 @@ module Google
484
482
  true
485
483
  end
486
484
 
487
- def default_headers
488
- { "google-cloud-resource-prefix" => "projects/#{@project}" }
485
+ def dead_letter_policy options
486
+ return nil unless options[:dead_letter_topic_name]
487
+ policy = Google::Cloud::PubSub::V1::DeadLetterPolicy.new dead_letter_topic: options[:dead_letter_topic_name]
488
+ if options[:dead_letter_max_delivery_attempts]
489
+ policy.max_delivery_attempts = options[:dead_letter_max_delivery_attempts]
490
+ end
491
+ policy
489
492
  end
490
493
 
491
- def default_options
492
- Google::Gax::CallOptions.new kwargs: default_headers
493
- end
494
+ private
495
+
496
+ def construct_create_subscription_options topic, subscription_name, options
497
+ excess_options = [:deadline,
498
+ :retention,
499
+ :retain_acked,
500
+ :message_ordering,
501
+ :endpoint,
502
+ :dead_letter_topic_name,
503
+ :dead_letter_max_delivery_attempts,
504
+ :dead_letter_topic]
505
+
506
+ new_options = options.filter { |k, v| !v.nil? && !excess_options.include?(k) }
507
+ new_options[:name] = subscription_path subscription_name, options
508
+ new_options[:topic] = topic_path topic
509
+ new_options[:message_retention_duration] = Convert.number_to_duration options[:retention]
510
+ new_options[:dead_letter_policy] = dead_letter_policy options
511
+ new_options[:ack_deadline_seconds] = options[:deadline]
512
+ new_options[:retain_acked_messages] = options[:retain_acked]
513
+ new_options[:enable_message_ordering] = options[:message_ordering]
494
514
 
495
- def execute
496
- yield
497
- rescue Google::Gax::GaxError => e
498
- # GaxError wraps BadStatus, but exposes it as #cause
499
- raise Google::Cloud::Error.from_error(e.cause)
515
+ new_options.compact
500
516
  end
501
517
  end
502
518
  end