google-cloud-pubsub 2.4.0 → 2.7.1

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.
@@ -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