google-cloud-pubsub 2.4.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,139 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/cloud/pubsub/errors"
17
+ require "concurrent/atomics"
18
+
19
+ module Google
20
+ module Cloud
21
+ module PubSub
22
+ ##
23
+ # @private
24
+ #
25
+ # Used to control the flow of messages passing through it.
26
+ #
27
+ class FlowController
28
+ attr_reader :message_limit
29
+ attr_reader :byte_limit
30
+ attr_reader :limit_exceeded_behavior
31
+ ##
32
+ # @private Implementation accessors
33
+ attr_reader :outstanding_messages, :outstanding_bytes, :awaiting
34
+
35
+ def initialize message_limit: 1000, byte_limit: 10_000_000, limit_exceeded_behavior: :ignore
36
+ unless [:ignore, :error, :block].include? limit_exceeded_behavior
37
+ raise ArgumentError, "limit_exceeded_behavior must be one of :ignore, :error, :block"
38
+ end
39
+ if [:error, :block].include?(limit_exceeded_behavior) && message_limit < 1
40
+ raise ArgumentError,
41
+ "Flow control message limit (#{message_limit}) exceeded by a single message, would block forever"
42
+ end
43
+ @mutex = Mutex.new
44
+ @message_limit = message_limit
45
+ @byte_limit = byte_limit
46
+ @limit_exceeded_behavior = limit_exceeded_behavior
47
+ @outstanding_messages = 0
48
+ @outstanding_bytes = 0
49
+
50
+ @awaiting = []
51
+ end
52
+
53
+ def acquire message_size
54
+ return if limit_exceeded_behavior == :ignore
55
+ @mutex.lock
56
+ if limit_exceeded_behavior == :error && would_exceed_message_limit?
57
+ raise FlowControlLimitError, "Flow control message limit (#{message_limit}) would be exceeded"
58
+ end
59
+ if limit_exceeded_behavior == :error && would_exceed_byte_limit?(message_size)
60
+ raise FlowControlLimitError,
61
+ "Flow control byte limit (#{byte_limit}) would be exceeded, message_size: #{message_size}"
62
+ end
63
+ if limit_exceeded_behavior == :block && message_size > byte_limit
64
+ raise FlowControlLimitError,
65
+ "Flow control byte limit (#{byte_limit}) exceeded by a single message, would block forever"
66
+ end
67
+
68
+ acquire_or_wait message_size
69
+ ensure
70
+ @mutex.unlock if @mutex.owned?
71
+ end
72
+
73
+ def release message_size
74
+ return if limit_exceeded_behavior == :ignore
75
+ @mutex.synchronize do
76
+ raise "Flow control messages count would be negative" if (@outstanding_messages - 1).negative?
77
+ raise "Flow control bytes count would be negative" if (@outstanding_bytes - message_size).negative?
78
+
79
+ @outstanding_messages -= 1
80
+ @outstanding_bytes -= message_size
81
+ @awaiting.first.set unless @awaiting.empty?
82
+ end
83
+ end
84
+
85
+ protected
86
+
87
+ # rubocop:disable Style/IdenticalConditionalBranches
88
+ # rubocop:disable Style/GuardClause
89
+
90
+ def acquire_or_wait message_size
91
+ waiter = nil
92
+ while is_new_and_others_wait?(waiter) ||
93
+ would_exceed_byte_limit?(message_size) ||
94
+ would_exceed_message_limit?
95
+
96
+ if waiter.nil?
97
+ waiter = Concurrent::Event.new
98
+ # This waiter gets added to the back of the line.
99
+ @awaiting << waiter
100
+ else
101
+ waiter = Concurrent::Event.new
102
+ # This waiter already in line stays at the head of the line.
103
+ @awaiting[0] = waiter
104
+ end
105
+ @mutex.unlock
106
+ waiter.wait
107
+ @mutex.lock
108
+ end
109
+ @outstanding_messages += 1
110
+ @outstanding_bytes += message_size
111
+
112
+ @awaiting.shift if waiter # Remove the newly released waiter from the head of the queue.
113
+
114
+ # There may be some surplus left; let the next message waiting try to acquire a permit.
115
+ if !@awaiting.empty? && @outstanding_bytes < byte_limit && @outstanding_messages < message_limit
116
+ @awaiting.first.set
117
+ end
118
+ end
119
+
120
+ # rubocop:enable Style/IdenticalConditionalBranches
121
+ # rubocop:enable Style/GuardClause
122
+
123
+ def is_new_and_others_wait? waiter
124
+ waiter.nil? && !@awaiting.empty?
125
+ end
126
+
127
+ def would_exceed_message_limit?
128
+ @outstanding_messages + 1 > message_limit
129
+ end
130
+
131
+ def would_exceed_byte_limit? bytes_requested
132
+ @outstanding_bytes + bytes_requested > byte_limit
133
+ end
134
+ end
135
+ end
136
+
137
+ Pubsub = PubSub unless const_defined? :Pubsub
138
+ end
139
+ end
@@ -18,6 +18,7 @@ require "google/cloud/pubsub/service"
18
18
  require "google/cloud/pubsub/credentials"
19
19
  require "google/cloud/pubsub/topic"
20
20
  require "google/cloud/pubsub/batch_publisher"
21
+ require "google/cloud/pubsub/schema"
21
22
  require "google/cloud/pubsub/snapshot"
22
23
 
23
24
  module Google
@@ -102,6 +103,16 @@ module Google
102
103
  # * `:threads` (Hash) The number of threads to create to handle concurrent calls by the publisher:
103
104
  # * `:publish` (Integer) The number of threads used to publish messages. Default is 2.
104
105
  # * `:callback` (Integer) The number of threads to handle the published messages' callbacks. Default is 4.
106
+ # * `:flow_control` (Hash) The client flow control settings for message publishing:
107
+ # * `:message_limit` (Integer) The maximum number of messages allowed to wait to be published. Default is
108
+ # `10 * max_messages`.
109
+ # * `:byte_limit` (Integer) The maximum total size of messages allowed to wait to be published. Default is
110
+ # `10 * max_bytes`.
111
+ # * `:limit_exceeded_behavior` (Symbol) The action to take when publish flow control limits are exceeded.
112
+ # Possible values include: `:ignore` - Flow control is disabled. `:error` - Calls to {Topic#publish_async}
113
+ # will raise {FlowControlLimitError} when publish flow control limits are exceeded. `:block` - Calls to
114
+ # {Topic#publish_async} will block until capacity is available when publish flow control limits are
115
+ # exceeded. The default value is `:ignore`.
105
116
  #
106
117
  # @return [Google::Cloud::PubSub::Topic, nil] Returns `nil` if topic
107
118
  # does not exist.
@@ -192,15 +203,41 @@ module Google
192
203
  #
193
204
  # Hash keys and values may include the following:
194
205
  #
195
- # * `:max_bytes` (Integer) The maximum size of messages to be collected before the batch is published. Default
196
- # is 1,000,000 (1MB).
197
- # * `:max_messages` (Integer) The maximum number of messages to be collected before the batch is published.
198
- # Default is 100.
199
- # * `:interval` (Numeric) The number of seconds to collect messages before the batch is published. Default is
200
- # 0.01.
201
- # * `:threads` (Hash) The number of threads to create to handle concurrent calls by the publisher:
202
- # * `:publish` (Integer) The number of threads used to publish messages. Default is 2.
203
- # * `:callback` (Integer) The number of threads to handle the published messages' callbacks. Default is 4.
206
+ # * `:max_bytes` (Integer) The maximum size of messages to be collected
207
+ # before the batch is published. Default is 1,000,000 (1MB).
208
+ # * `:max_messages` (Integer) The maximum number of messages to be
209
+ # collected before the batch is published. Default is 100.
210
+ # * `:interval` (Numeric) The number of seconds to collect messages before
211
+ # the batch is published. Default is 0.01.
212
+ # * `:threads` (Hash) The number of threads to create to handle concurrent
213
+ # calls by the publisher:
214
+ #
215
+ # * `:publish` (Integer) The number of threads used to publish messages.
216
+ # Default is 2.
217
+ # * `:callback` (Integer) The number of threads to handle the published
218
+ # messages' callbacks. Default is 4.
219
+ # * `:flow_control` (Hash) The client flow control settings for message publishing:
220
+ # * `:message_limit` (Integer) The maximum number of messages allowed to wait to be published. Default is
221
+ # `10 * max_messages`.
222
+ # * `:byte_limit` (Integer) The maximum total size of messages allowed to wait to be published. Default is
223
+ # `10 * max_bytes`.
224
+ # * `:limit_exceeded_behavior` (Symbol) The action to take when publish flow control limits are exceeded.
225
+ # Possible values include: `:ignore` - Flow control is disabled. `:error` - Calls to {Topic#publish_async}
226
+ # will raise {FlowControlLimitError} when publish flow control limits are exceeded. `:block` - Calls to
227
+ # {Topic#publish_async} will block until capacity is available when publish flow control limits are
228
+ # exceeded. The default value is `:ignore`.
229
+ # @param [String] schema_name The name of the schema that messages
230
+ # published should be validated against. Optional. The value can be a
231
+ # simple schema ID (relative name), in which case the current project
232
+ # ID will be supplied, or a fully-qualified schema name in the form
233
+ # `projects/{project_id}/schemas/{schema_id}`. If provided,
234
+ # `message_encoding` must also be provided.
235
+ # @param [String, Symbol] message_encoding The encoding of messages validated
236
+ # against the schema identified by `schema_name`. Optional. Values include:
237
+ #
238
+ # * `JSON` - JSON encoding.
239
+ # * `BINARY` - Binary encoding, as defined by the schema type. For some
240
+ # schema types, binary encoding may not be available.
204
241
  #
205
242
  # @return [Google::Cloud::PubSub::Topic]
206
243
  #
@@ -210,12 +247,20 @@ module Google
210
247
  # pubsub = Google::Cloud::PubSub.new
211
248
  # topic = pubsub.create_topic "my-topic"
212
249
  #
213
- def create_topic topic_name, labels: nil, kms_key: nil, persistence_regions: nil, async: nil
250
+ def create_topic topic_name,
251
+ labels: nil,
252
+ kms_key: nil,
253
+ persistence_regions: nil,
254
+ async: nil,
255
+ schema_name: nil,
256
+ message_encoding: nil
214
257
  ensure_service!
215
258
  grpc = service.create_topic topic_name,
216
259
  labels: labels,
217
260
  kms_key_name: kms_key,
218
- persistence_regions: persistence_regions
261
+ persistence_regions: persistence_regions,
262
+ schema_name: schema_name,
263
+ message_encoding: message_encoding
219
264
  Topic.from_grpc grpc, service, async: async
220
265
  end
221
266
  alias new_topic create_topic
@@ -387,6 +432,198 @@ module Google
387
432
  alias find_snapshots snapshots
388
433
  alias list_snapshots snapshots
389
434
 
435
+ ##
436
+ # Retrieves schema by name.
437
+ #
438
+ # @param [String] schema_name Name of a schema. The value can
439
+ # be a simple schema ID, in which case the current project ID
440
+ # will be supplied, or a fully-qualified schema name in the form
441
+ # `projects/{project_id}/schemas/{schema_id}`.
442
+ # @param view [Symbol, String, nil] Possible values:
443
+ # * `BASIC` - Include the `name` and `type` of the schema, but not the `definition`.
444
+ # * `FULL` - Include all Schema object fields.
445
+ #
446
+ # The default value is `FULL`.
447
+ # @param [String] project If the schema belongs to a project other
448
+ # than the one currently connected to, the alternate project ID can be
449
+ # specified here. Not used if a fully-qualified schema name is
450
+ # provided for `schema_name`.
451
+ # @param [Boolean] skip_lookup Optionally create a {Schema} object
452
+ # without verifying the schema resource exists on the Pub/Sub
453
+ # service. Calls made on this object will raise errors if the service
454
+ # resource does not exist. Default is `false`.
455
+ #
456
+ # @return [Google::Cloud::PubSub::Schema, nil] Returns `nil` if
457
+ # the schema does not exist.
458
+ #
459
+ # @example
460
+ # require "google/cloud/pubsub"
461
+ #
462
+ # pubsub = Google::Cloud::PubSub.new
463
+ #
464
+ # schema = pubsub.schema "my-schema"
465
+ # schema.name #=> "projects/my-project/schemas/my-schema"
466
+ # schema.type #=> :PROTOCOL_BUFFER
467
+ # schema.definition # The schema definition
468
+ #
469
+ # @example Skip the lookup against the service with `skip_lookup`:
470
+ # require "google/cloud/pubsub"
471
+ #
472
+ # pubsub = Google::Cloud::PubSub.new
473
+ #
474
+ # # No API call is made to retrieve the schema information.
475
+ # # The default project is used in the name.
476
+ # schema = pubsub.schema "my-schema", skip_lookup: true
477
+ # schema.name #=> "projects/my-project/schemas/my-schema"
478
+ # schema.type #=> nil
479
+ # schema.definition #=> nil
480
+ #
481
+ # @example Omit the schema definition with `view: :basic`:
482
+ # require "google/cloud/pubsub"
483
+ #
484
+ # pubsub = Google::Cloud::PubSub.new
485
+ #
486
+ # schema = pubsub.schema "my-schema", view: :basic
487
+ # schema.name #=> "projects/my-project/schemas/my-schema"
488
+ # schema.type #=> :PROTOCOL_BUFFER
489
+ # schema.definition #=> nil
490
+ #
491
+ def schema schema_name, view: nil, project: nil, skip_lookup: nil
492
+ ensure_service!
493
+ options = { project: project }
494
+ return Schema.from_name schema_name, view, service, options if skip_lookup
495
+ view ||= :FULL
496
+ grpc = service.get_schema schema_name, view, options
497
+ Schema.from_grpc grpc, service
498
+ rescue Google::Cloud::NotFoundError
499
+ nil
500
+ end
501
+ alias get_schema schema
502
+ alias find_schema schema
503
+
504
+ ##
505
+ # Creates a new schema.
506
+ #
507
+ # @param [String] schema_id The ID to use for the schema, which will
508
+ # become the final component of the schema's resource name. Required.
509
+ #
510
+ # The schema ID (relative name) must start with a letter, and
511
+ # contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),
512
+ # underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent
513
+ # signs (`%`). It must be between 3 and 255 characters in length, and
514
+ # it must not start with `goog`.
515
+ # @param [String, Symbol] type The type of the schema. Required. Possible
516
+ # values are case-insensitive and include:
517
+ #
518
+ # * `PROTOCOL_BUFFER` - A Protocol Buffer schema definition.
519
+ # * `AVRO` - An Avro schema definition.
520
+ # @param [String] definition The definition of the schema. Required. This
521
+ # should be a string representing the full definition of the schema that
522
+ # is a valid schema definition of the type specified in `type`.
523
+ # @param [String] project If the schema belongs to a project other
524
+ # than the one currently connected to, the alternate project ID can be
525
+ # specified here. Optional.
526
+ #
527
+ # @return [Google::Cloud::PubSub::Schema]
528
+ #
529
+ # @example
530
+ # require "google/cloud/pubsub"
531
+ #
532
+ # pubsub = Google::Cloud::PubSub.new
533
+ #
534
+ # definition = "..."
535
+ # schema = pubsub.create_schema "my-schema", :avro, definition
536
+ # schema.name #=> "projects/my-project/schemas/my-schema"
537
+ #
538
+ def create_schema schema_id, type, definition, project: nil
539
+ ensure_service!
540
+ type = type.to_s.upcase
541
+ grpc = service.create_schema schema_id, type, definition, project: project
542
+ Schema.from_grpc grpc, service
543
+ end
544
+ alias new_schema create_schema
545
+
546
+ ##
547
+ # Retrieves a list of schemas for the given project.
548
+ #
549
+ # @param view [String, Symbol, nil] The set of fields to return in the response. Possible values:
550
+ #
551
+ # * `BASIC` - Include the `name` and `type` of the schema, but not the `definition`.
552
+ # * `FULL` - Include all Schema object fields.
553
+ #
554
+ # The default value is `FULL`.
555
+ # @param [String] token A previously-returned page token representing
556
+ # part of the larger set of results to view.
557
+ # @param [Integer] max Maximum number of schemas to return.
558
+ #
559
+ # @return [Array<Google::Cloud::PubSub::Schema>] (See
560
+ # {Google::Cloud::PubSub::Schema::List})
561
+ #
562
+ # @example
563
+ # require "google/cloud/pubsub"
564
+ #
565
+ # pubsub = Google::Cloud::PubSub.new
566
+ #
567
+ # schemas = pubsub.schemas
568
+ # schemas.each do |schema|
569
+ # puts schema.name
570
+ # end
571
+ #
572
+ # @example Retrieve all schemas: (See {Schema::List#all})
573
+ # require "google/cloud/pubsub"
574
+ #
575
+ # pubsub = Google::Cloud::PubSub.new
576
+ #
577
+ # schemas = pubsub.schemas
578
+ # schemas.all do |schema|
579
+ # puts schema.name
580
+ # end
581
+ #
582
+ def schemas view: nil, token: nil, max: nil
583
+ ensure_service!
584
+ view ||= :FULL
585
+ options = { token: token, max: max }
586
+ grpc = service.list_schemas view, options
587
+ Schema::List.from_grpc grpc, service, view, max
588
+ end
589
+ alias find_schemas schemas
590
+ alias list_schemas schemas
591
+
592
+ ##
593
+ # Validates a schema type and definition.
594
+ #
595
+ # @param [String, Symbol] type The type of the schema. Required. Possible
596
+ # values are case-insensitive and include:
597
+ #
598
+ # * `PROTOCOL_BUFFER` - A Protocol Buffer schema definition.
599
+ # * `AVRO` - An Avro schema definition.
600
+ # @param [String] definition The definition of the schema. Required. This
601
+ # should be a string representing the full definition of the schema that
602
+ # is a valid schema definition of the type specified in `type`.
603
+ # @param [String] project If the schema belongs to a project other
604
+ # than the one currently connected to, the alternate project ID can be
605
+ # specified here. Optional.
606
+ #
607
+ # @return [Boolean] `true` if the schema is valid, `false` otherwise.
608
+ #
609
+ # @example
610
+ # require "google/cloud/pubsub"
611
+ #
612
+ # pubsub = Google::Cloud::PubSub.new
613
+ #
614
+ # definition = "..."
615
+ # pubsub.validate_schema :avro, definition #=> true
616
+ #
617
+ def valid_schema? type, definition, project: nil
618
+ ensure_service!
619
+ type = type.to_s.upcase
620
+ service.validate_schema type, definition, project: project # return type is empty
621
+ true
622
+ rescue Google::Cloud::InvalidArgumentError
623
+ false
624
+ end
625
+ alias validate_schema valid_schema?
626
+
390
627
  protected
391
628
 
392
629
  ##
@@ -0,0 +1,310 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/cloud/pubsub/schema/list"
17
+ require "google/cloud/pubsub/v1"
18
+
19
+ module Google
20
+ module Cloud
21
+ module PubSub
22
+ ##
23
+ # # Schema
24
+ #
25
+ # A schema resource.
26
+ #
27
+ # @example
28
+ # require "google/cloud/pubsub"
29
+ #
30
+ # pubsub = Google::Cloud::PubSub.new
31
+ #
32
+ # schema = pubsub.schema "my-schema"
33
+ # schema.name #=> "projects/my-project/schemas/my-schema"
34
+ # schema.type #=> :PROTOCOL_BUFFER
35
+ #
36
+ class Schema
37
+ ##
38
+ # @private The Service object.
39
+ attr_accessor :service
40
+
41
+ ##
42
+ # @private The gRPC Google::Cloud::PubSub::V1::Schema object.
43
+ attr_accessor :grpc
44
+
45
+ ##
46
+ # @private Create a new Schema instance.
47
+ def initialize grpc, service, view: nil
48
+ @grpc = grpc
49
+ @service = service
50
+ @exists = nil
51
+ @view = view || :FULL
52
+ end
53
+
54
+ ##
55
+ # The name of the schema.
56
+ #
57
+ # @return [String] A fully-qualified schema name in the form `projects/{project_id}/schemas/{schema_id}`.
58
+ #
59
+ def name
60
+ @grpc.name
61
+ end
62
+
63
+ ##
64
+ # The type of the schema. Possible values include:
65
+ #
66
+ # * `PROTOCOL_BUFFER` - A Protocol Buffer schema definition.
67
+ # * `AVRO` - An Avro schema definition.
68
+ #
69
+ # @return [String, nil] The upper-case type name.
70
+ #
71
+ def type
72
+ return nil if reference?
73
+ @grpc.type
74
+ end
75
+
76
+ ##
77
+ # The definition of the schema. This should be a string representing the full definition of the schema that is a
78
+ # valid schema definition of the type specified in {#type}.
79
+ #
80
+ # @return [String, nil] The schema definition.
81
+ #
82
+ def definition
83
+ return nil if reference?
84
+ @grpc.definition if @grpc.definition && !@grpc.definition.empty?
85
+ end
86
+
87
+ ##
88
+ # Validates a message against a schema.
89
+ #
90
+ # @param message_data [String] Message to validate against the provided `schema_spec`.
91
+ # @param message_encoding [Symbol, String] The encoding of the message validated against the schema. Values
92
+ # include:
93
+ #
94
+ # * `JSON` - JSON encoding.
95
+ # * `BINARY` - Binary encoding, as defined by the schema type. For some schema types, binary encoding may not
96
+ # be available.
97
+ #
98
+ # @return [Boolean] Returns `true` if the message validiation succeeds, `false` otherwise.
99
+ #
100
+ # @example
101
+ # require "google/cloud/pubsub"
102
+ #
103
+ # pubsub = Google::Cloud::PubSub.new
104
+ # schema = pubsub.schema "my-schema"
105
+ #
106
+ # message_data = { "name" => "Alaska", "post_abbr" => "AK" }.to_json
107
+ # schema.validate_message message_data, :json
108
+ #
109
+ def validate_message message_data, message_encoding
110
+ message_encoding = message_encoding.to_s.upcase
111
+ service.validate_message message_data, message_encoding, schema_name: name
112
+ true
113
+ rescue Google::Cloud::InvalidArgumentError
114
+ false
115
+ end
116
+
117
+ ##
118
+ # Removes the schema, if it exists.
119
+ #
120
+ # @return [Boolean] Returns `true` if the schema was deleted.
121
+ #
122
+ # @example
123
+ # require "google/cloud/pubsub"
124
+ #
125
+ # pubsub = Google::Cloud::PubSub.new
126
+ # schema = pubsub.schema "my-schema"
127
+ #
128
+ # schema.delete
129
+ #
130
+ def delete
131
+ ensure_service!
132
+ service.delete_schema name
133
+ true
134
+ end
135
+
136
+ ##
137
+ # Reloads the schema with current data from the Pub/Sub service.
138
+ #
139
+ # @param view [Symbol, String, nil] The set of fields to return in the response. Possible values:
140
+ # * `BASIC` - Include the `name` and `type` of the schema, but not the `definition`.
141
+ # * `FULL` - Include all Schema object fields.
142
+ #
143
+ # Optional. If not provided or `nil`, the last non-nil `view` argument to this method will be used if one has
144
+ # been given, othewise `FULL` will be used.
145
+ #
146
+ # @return [Google::Cloud::PubSub::Schema] Returns the reloaded schema.
147
+ #
148
+ # @example Skip retrieving the schema from the service, then load it:
149
+ # require "google/cloud/pubsub"
150
+ #
151
+ # pubsub = Google::Cloud::PubSub.new
152
+ # schema = pubsub.schema "my-schema", skip_lookup: true
153
+ #
154
+ # schema.reload!
155
+ #
156
+ # @example Use the `view` option to load the basic or full resource:
157
+ # require "google/cloud/pubsub"
158
+ #
159
+ # pubsub = Google::Cloud::PubSub.new
160
+ # schema = pubsub.schema "my-schema", view: :basic
161
+ # schema.resource_partial? #=> true
162
+ #
163
+ # schema.reload! view: :full
164
+ # schema.resource_partial? #=> false
165
+ #
166
+ # @!group Lifecycle
167
+ #
168
+ def reload! view: nil
169
+ ensure_service!
170
+ @view = view || @view
171
+ @grpc = service.get_schema name, @view
172
+ @reference = nil
173
+ @exists = nil
174
+ self
175
+ end
176
+ alias refresh! reload!
177
+
178
+ ##
179
+ # Determines whether the schema exists in the Pub/Sub service.
180
+ #
181
+ # @example
182
+ # require "google/cloud/pubsub"
183
+ #
184
+ # pubsub = Google::Cloud::PubSub.new
185
+ #
186
+ # schema = pubsub.schema "my-schema"
187
+ # schema.exists? #=> true
188
+ #
189
+ def exists?
190
+ # Always true if the object is not set as reference
191
+ return true unless reference?
192
+ # If we have a value, return it
193
+ return @exists unless @exists.nil?
194
+ ensure_grpc!
195
+ @exists = true
196
+ rescue Google::Cloud::NotFoundError
197
+ @exists = false
198
+ end
199
+
200
+ ##
201
+ # Determines whether the schema object was created without retrieving the
202
+ # resource representation from the Pub/Sub service.
203
+ #
204
+ # @return [Boolean] `true` when the schema was created without a resource
205
+ # representation, `false` otherwise.
206
+ #
207
+ # @example
208
+ # require "google/cloud/pubsub"
209
+ #
210
+ # pubsub = Google::Cloud::PubSub.new
211
+ #
212
+ # schema = pubsub.schema "my-schema", skip_lookup: true
213
+ # schema.reference? #=> true
214
+ #
215
+ def reference?
216
+ @grpc.type.nil? || @grpc.type == :TYPE_UNSPECIFIED
217
+ end
218
+
219
+ ##
220
+ # Determines whether the schema object was created with a resource
221
+ # representation from the Pub/Sub service.
222
+ #
223
+ # @return [Boolean] `true` when the schema was created with a resource
224
+ # representation, `false` otherwise.
225
+ #
226
+ # @example
227
+ # require "google/cloud/pubsub"
228
+ #
229
+ # pubsub = Google::Cloud::PubSub.new
230
+ #
231
+ # schema = pubsub.schema "my-schema"
232
+ # schema.resource? #=> true
233
+ #
234
+ def resource?
235
+ !reference?
236
+ end
237
+
238
+ ##
239
+ # Whether the schema was created with a partial resource representation
240
+ # from the Pub/Sub service.
241
+ #
242
+ # @return [Boolean] `true` when the schema was created with a partial
243
+ # resource representation, `false` otherwise.
244
+ #
245
+ # @example
246
+ # require "google/cloud/pubsub"
247
+ #
248
+ # pubsub = Google::Cloud::PubSub.new
249
+ # schema = pubsub.schema "my-schema", view: :basic
250
+ #
251
+ # schema.resource_partial? #=> true
252
+ # schema.reload! view: :full # Loads the full resource.
253
+ # schema.resource_partial? #=> false
254
+ #
255
+ def resource_partial?
256
+ resource? && !resource_full?
257
+ end
258
+
259
+ ##
260
+ # Whether the schema was created with a full resource representation
261
+ # from the Pub/Sub service.
262
+ #
263
+ # @return [Boolean] `true` when the schema was created with a full
264
+ # resource representation, `false` otherwise.
265
+ #
266
+ # @example
267
+ # require "google/cloud/pubsub"
268
+ #
269
+ # pubsub = Google::Cloud::PubSub.new
270
+ # schema = pubsub.schema "my-schema"
271
+ #
272
+ # schema.resource_full? #=> true
273
+ #
274
+ def resource_full?
275
+ resource? && @grpc.definition && !@grpc.definition.empty?
276
+ end
277
+
278
+ ##
279
+ # @private New Schema from a Google::Cloud::PubSub::V1::Schema object.
280
+ def self.from_grpc grpc, service, view: nil
281
+ new grpc, service, view: view
282
+ end
283
+
284
+ ##
285
+ # @private New reference Schema object without making an HTTP request.
286
+ def self.from_name name, view, service, options = {}
287
+ grpc = Google::Cloud::PubSub::V1::Schema.new name: service.schema_path(name, options)
288
+ from_grpc grpc, service, view: view
289
+ end
290
+
291
+ protected
292
+
293
+ ##
294
+ # @private Raise an error unless an active connection to the service is available.
295
+ def ensure_service!
296
+ raise "Must have active connection to service" unless service
297
+ end
298
+
299
+ ##
300
+ # Ensures a Google::Cloud::PubSub::V1::Schema object exists.
301
+ def ensure_grpc!
302
+ ensure_service!
303
+ reload! if reference?
304
+ end
305
+ end
306
+ end
307
+
308
+ Pubsub = PubSub unless const_defined? :Pubsub
309
+ end
310
+ end