google-cloud-pubsub 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ # Copyright 2015 Google Inc. All rights reserved.
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
+ # http://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/credentials"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Pubsub
21
+ ##
22
+ # @private Represents the OAuth 2.0 signing logic for Pub/Sub.
23
+ class Credentials < Google::Cloud::Credentials
24
+ SCOPE = ["https://www.googleapis.com/auth/pubsub"]
25
+ PATH_ENV_VARS = %w(PUBSUB_KEYFILE GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
26
+ JSON_ENV_VARS = %w(PUBSUB_KEYFILE_JSON GOOGLE_CLOUD_KEYFILE_JSON
27
+ GCLOUD_KEYFILE_JSON)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ # Copyright 2015 Google Inc. All rights reserved.
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
+ # http://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/errors"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Pubsub
21
+ ##
22
+ # # Message
23
+ #
24
+ # Represents a Pub/Sub Message.
25
+ #
26
+ # Message objects are created by {Topic#publish}. {Subscription#pull}
27
+ # returns an array of {ReceivedMessage} objects, each of which contains a
28
+ # Message object. Each {ReceivedMessage} object can be acknowledged and/or
29
+ # delayed.
30
+ #
31
+ # @example
32
+ # require "google/cloud"
33
+ #
34
+ # gcloud = Google::Cloud.new
35
+ # pubsub = gcloud.pubsub
36
+ #
37
+ # # Publish a message
38
+ # topic = pubsub.topic "my-topic"
39
+ # message = topic.publish "new-message"
40
+ # puts message.data #=> "new-message"
41
+ #
42
+ # # Pull a message
43
+ # sub = pubsub.subscription "my-topic-sub"
44
+ # received_message = sub.pull.first
45
+ # puts received_message.message.data #=> "new-message"
46
+ #
47
+ class Message
48
+ ##
49
+ # @private The gRPC Google::Pubsub::V1::PubsubMessage object.
50
+ attr_accessor :grpc
51
+
52
+ ##
53
+ # Create an empty Message object.
54
+ # This can be used to publish several messages in bulk.
55
+ def initialize data = nil, attributes = {}
56
+ # Convert attributes to strings to match the protobuf definition
57
+ attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
58
+
59
+ @grpc = Google::Pubsub::V1::PubsubMessage.new(
60
+ data: String(data).encode("ASCII-8BIT"),
61
+ attributes: attributes)
62
+ end
63
+
64
+ ##
65
+ # The received data.
66
+ def data
67
+ @grpc.data
68
+ end
69
+
70
+ ##
71
+ # The received attributes.
72
+ def attributes
73
+ return @grpc.attributes.to_h if @grpc.attributes.respond_to? :to_h
74
+ # Enumerable doesn't have to_h on Ruby 2.0, so fallback to this
75
+ Hash[@grpc.attributes.to_a]
76
+ end
77
+
78
+ ##
79
+ # The ID of this message, assigned by the server at publication time.
80
+ # Guaranteed to be unique within the topic.
81
+ def message_id
82
+ @grpc.message_id
83
+ end
84
+ alias_method :msg_id, :message_id
85
+
86
+ ##
87
+ # @private New Message from a Google::Pubsub::V1::PubsubMessage object.
88
+ def self.from_grpc grpc
89
+ new.tap do |m|
90
+ m.instance_variable_set "@grpc", grpc
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,209 @@
1
+ # Copyright 2016 Google Inc. All rights reserved.
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
+ # http://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/errors"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Pubsub
21
+ ##
22
+ # # Policy
23
+ #
24
+ # Represents a Cloud IAM Policy for the Pub/Sub service.
25
+ #
26
+ # A common pattern for updating a resource's metadata, such as its Policy,
27
+ # is to read the current data from the service, update the data locally,
28
+ # and then send the modified data for writing. This pattern may result in
29
+ # a conflict if two or more processes attempt the sequence simultaneously.
30
+ # IAM solves this problem with the {Google::Cloud::Pubsub::Policy#etag}
31
+ # property, which is used to verify whether the policy has changed since
32
+ # the last request. When you make a request to with an `etag` value, Cloud
33
+ # IAM compares the `etag` value in the request with the existing `etag`
34
+ # value associated with the policy. It writes the policy only if the
35
+ # `etag` values match.
36
+ #
37
+ # When you update a policy, first read the policy (and its current `etag`)
38
+ # from the service, then modify the policy locally, and then write the
39
+ # modified policy to the service. See
40
+ # {Google::Cloud::Pubsub::Topic#policy} and
41
+ # {Google::Cloud::Pubsub::Topic#policy=}.
42
+ #
43
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing
44
+ # policies
45
+ # @see https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#iampolicy
46
+ # google.iam.v1.IAMPolicy
47
+ #
48
+ # @attr [String] etag Used to verify whether the policy has changed since
49
+ # the last request. The policy will be written only if the `etag` values
50
+ # match.
51
+ # @attr [Hash{String => Array<String>}] roles The bindings that associate
52
+ # roles with an array of members. See [Understanding
53
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
54
+ # listing of primitive and curated roles.
55
+ # See [Binding](https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#binding)
56
+ # for a listing of values and patterns for members.
57
+ #
58
+ # @example
59
+ # require "google/cloud"
60
+ #
61
+ # gcloud = Google::Cloud.new
62
+ # pubsub = gcloud.pubsub
63
+ # topic = pubsub.topic "my-topic"
64
+ #
65
+ # policy = topic.policy # API call
66
+ #
67
+ # policy.remove "roles/owner", "user:owner@example.com" # Local call
68
+ # policy.add "roles/owner", "user:newowner@example.com" # Local call
69
+ # policy.roles["roles/viewer"] = ["allUsers"] # Local call
70
+ #
71
+ # topic.policy = policy # API call
72
+ #
73
+ class Policy
74
+ attr_reader :etag, :roles
75
+
76
+ ##
77
+ # @private Creates a Policy object.
78
+ def initialize etag, roles
79
+ @etag = etag
80
+ @roles = roles
81
+ end
82
+
83
+ ##
84
+ # Convenience method for adding a member to a binding on this policy.
85
+ # See [Understanding
86
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
87
+ # listing of primitive and curated roles.
88
+ # See [Binding](https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#binding)
89
+ # for a listing of values and patterns for members.
90
+ #
91
+ # @param [String] role_name A Cloud IAM role, such as
92
+ # `"roles/pubsub.admin"`.
93
+ # @param [String] member A Cloud IAM identity, such as
94
+ # `"user:owner@example.com"`.
95
+ #
96
+ # @example
97
+ # require "google/cloud"
98
+ #
99
+ # gcloud = Google::Cloud.new
100
+ # pubsub = gcloud.pubsub
101
+ # topic = pubsub.topic "my-topic"
102
+ #
103
+ # policy = topic.policy # API call
104
+ #
105
+ # policy.add "roles/owner", "user:newowner@example.com" # Local call
106
+ #
107
+ # topic.policy = policy # API call
108
+ #
109
+ def add role_name, member
110
+ role(role_name) << member
111
+ end
112
+
113
+ ##
114
+ # Convenience method for removing a member from a binding on this
115
+ # policy. See [Understanding
116
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
117
+ # listing of primitive and curated roles. See
118
+ # [Binding](https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#binding)
119
+ # for a listing of values and patterns for members.
120
+ #
121
+ # @param [String] role_name A Cloud IAM role, such as
122
+ # `"roles/pubsub.admin"`.
123
+ # @param [String] member A Cloud IAM identity, such as
124
+ # `"user:owner@example.com"`.
125
+ #
126
+ # @example
127
+ # require "google/cloud"
128
+ #
129
+ # gcloud = Google::Cloud.new
130
+ # pubsub = gcloud.pubsub
131
+ # topic = pubsub.topic "my-topic"
132
+ #
133
+ # policy = topic.policy # API call
134
+ #
135
+ # policy.remove "roles/owner", "user:owner@example.com" # Local call
136
+ #
137
+ # topic.policy = policy # API call
138
+ #
139
+ def remove role_name, member
140
+ role(role_name).delete member
141
+ end
142
+
143
+ ##
144
+ # Convenience method returning the array of members bound to a role in
145
+ # this policy, or an empty array if no value is present for the role in
146
+ # {#roles}. See [Understanding
147
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
148
+ # listing of primitive and curated roles. See
149
+ # [Binding](https://cloud.google.com/pubsub/reference/rpc/google.iam.v1#binding)
150
+ # for a listing of values and patterns for members.
151
+ #
152
+ # @return [Array<String>] The members strings, or an empty array.
153
+ #
154
+ # @example
155
+ # require "google/cloud"
156
+ #
157
+ # gcloud = Google::Cloud.new
158
+ # pubsub = gcloud.pubsub
159
+ # topic = pubsub.topic "my-topic"
160
+ #
161
+ # policy = topic.policy
162
+ #
163
+ # policy.role("roles/viewer") << "user:viewer@example.com"
164
+ #
165
+ def role role_name
166
+ roles[role_name] ||= []
167
+ end
168
+
169
+ ##
170
+ # Returns a deep copy of the policy.
171
+ #
172
+ # @return [Policy]
173
+ #
174
+ def deep_dup
175
+ dup.tap do |p|
176
+ roles_dup = p.roles.each_with_object({}) do |(k, v), memo|
177
+ memo[k] = v.dup rescue value
178
+ end
179
+ p.instance_variable_set "@roles", roles_dup
180
+ end
181
+ end
182
+
183
+ ##
184
+ # @private Convert the Policy to a Google::Iam::V1::Policy object.
185
+ def to_grpc
186
+ Google::Iam::V1::Policy.new(
187
+ etag: etag,
188
+ bindings: roles.keys.map do |role_name|
189
+ next if roles[role_name].empty?
190
+ Google::Iam::V1::Binding.new(
191
+ role: role_name,
192
+ members: roles[role_name]
193
+ )
194
+ end
195
+ )
196
+ end
197
+
198
+ ##
199
+ # @private New Policy from a Google::Iam::V1::Policy object.
200
+ def self.from_grpc grpc
201
+ roles = grpc.bindings.each_with_object({}) do |binding, memo|
202
+ memo[binding.role] = binding.members.to_a
203
+ end
204
+ new grpc.etag, roles
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,487 @@
1
+ # Copyright 2015 Google Inc. All rights reserved.
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
+ # http://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/errors"
17
+ require "google/cloud/core/gce"
18
+ require "google/cloud/pubsub/service"
19
+ require "google/cloud/pubsub/credentials"
20
+ require "google/cloud/pubsub/topic"
21
+
22
+ module Google
23
+ module Cloud
24
+ module Pubsub
25
+ ##
26
+ # # Project
27
+ #
28
+ # Represents the project that pubsub messages are pushed to and pulled
29
+ # from. {Topic} is a named resource to which messages are sent by
30
+ # publishers. {Subscription} is a named resource representing the stream
31
+ # of messages from a single, specific topic, to be delivered to the
32
+ # subscribing application. {Message} is a combination of data and
33
+ # attributes that a publisher sends to a topic and is eventually delivered
34
+ # to subscribers.
35
+ #
36
+ # See {Google::Cloud#pubsub}
37
+ #
38
+ # @example
39
+ # require "google/cloud"
40
+ #
41
+ # gcloud = Google::Cloud.new
42
+ # pubsub = gcloud.pubsub
43
+ #
44
+ # topic = pubsub.topic "my-topic"
45
+ # topic.publish "task completed"
46
+ #
47
+ class Project
48
+ ##
49
+ # @private The gRPC Service object.
50
+ attr_accessor :service
51
+
52
+ ##
53
+ # @private Creates a new Pub/Sub Project instance.
54
+ def initialize service
55
+ @service = service
56
+ end
57
+
58
+ # The Pub/Sub project connected to.
59
+ #
60
+ # @example
61
+ # require "google/cloud"
62
+ #
63
+ # gcloud = Google::Cloud.new "my-todo-project",
64
+ # "/path/to/keyfile.json"
65
+ # pubsub = gcloud.pubsub
66
+ #
67
+ # pubsub.project #=> "my-todo-project"
68
+ #
69
+ def project
70
+ service.project
71
+ end
72
+
73
+ ##
74
+ # @private Default project.
75
+ def self.default_project
76
+ ENV["PUBSUB_PROJECT"] ||
77
+ ENV["GOOGLE_CLOUD_PROJECT"] ||
78
+ ENV["GCLOUD_PROJECT"] ||
79
+ Google::Cloud::Core::GCE.project_id
80
+ end
81
+
82
+ ##
83
+ # Retrieves topic by name.
84
+ #
85
+ # The topic will be created if the topic does not exist and the
86
+ # `autocreate` option is set to true.
87
+ #
88
+ # @param [String] topic_name Name of a topic.
89
+ # @param [Boolean] autocreate Flag to control whether the requested
90
+ # topic will be created if it does not exist. Ignored if `skip_lookup`
91
+ # is `true`. The default value is `false`.
92
+ # @param [String] project If the topic belongs to a project other than
93
+ # the one currently connected to, the alternate project ID can be
94
+ # specified here.
95
+ # @param [Boolean] skip_lookup Optionally create a {Topic} object
96
+ # without verifying the topic resource exists on the Pub/Sub service.
97
+ # Calls made on this object will raise errors if the topic resource
98
+ # does not exist. Default is `false`.
99
+ #
100
+ # @return [Google::Cloud::Pubsub::Topic, nil] Returns `nil` if topic
101
+ # does not exist. Will return a newly created{
102
+ # Google::Cloud::Pubsub::Topic} if the topic does not exist and
103
+ # `autocreate` is set to `true`.
104
+ #
105
+ # @example
106
+ # require "google/cloud"
107
+ #
108
+ # gcloud = Google::Cloud.new
109
+ # pubsub = gcloud.pubsub
110
+ # topic = pubsub.topic "existing-topic"
111
+ #
112
+ # @example By default `nil` will be returned if topic does not exist.
113
+ # require "google/cloud"
114
+ #
115
+ # gcloud = Google::Cloud.new
116
+ # pubsub = gcloud.pubsub
117
+ # topic = pubsub.topic "non-existing-topic" #=> nil
118
+ #
119
+ # @example With the `autocreate` option set to `true`.
120
+ # require "google/cloud"
121
+ #
122
+ # gcloud = Google::Cloud.new
123
+ # pubsub = gcloud.pubsub
124
+ # topic = pubsub.topic "non-existing-topic", autocreate: true
125
+ #
126
+ # @example Create topic in a different project with the `project` flag.
127
+ # require "google/cloud"
128
+ #
129
+ # gcloud = Google::Cloud.new
130
+ # pubsub = gcloud.pubsub
131
+ # topic = pubsub.topic "another-topic", project: "another-project"
132
+ #
133
+ # @example Skip the lookup against the service with `skip_lookup`:
134
+ # require "google/cloud"
135
+ #
136
+ # gcloud = Google::Cloud.new
137
+ # pubsub = gcloud.pubsub
138
+ # topic = pubsub.topic "another-topic", skip_lookup: true
139
+ #
140
+ def topic topic_name, autocreate: nil, project: nil, skip_lookup: nil
141
+ ensure_service!
142
+ options = { project: project }
143
+ return Topic.new_lazy(topic_name, service, options) if skip_lookup
144
+ grpc = service.get_topic topic_name
145
+ Topic.from_grpc grpc, service
146
+ rescue Google::Cloud::NotFoundError
147
+ return create_topic(topic_name) if autocreate
148
+ nil
149
+ end
150
+ alias_method :get_topic, :topic
151
+ alias_method :find_topic, :topic
152
+
153
+ ##
154
+ # Creates a new topic.
155
+ #
156
+ # @param [String] topic_name Name of a topic.
157
+ #
158
+ # @return [Google::Cloud::Pubsub::Topic]
159
+ #
160
+ # @example
161
+ # require "google/cloud"
162
+ #
163
+ # gcloud = Google::Cloud.new
164
+ # pubsub = gcloud.pubsub
165
+ # topic = pubsub.create_topic "my-topic"
166
+ #
167
+ def create_topic topic_name
168
+ ensure_service!
169
+ grpc = service.create_topic topic_name
170
+ Topic.from_grpc grpc, service
171
+ end
172
+ alias_method :new_topic, :create_topic
173
+
174
+ ##
175
+ # Retrieves a list of topics for the given project.
176
+ #
177
+ # @param [String] token The `token` value returned by the last call to
178
+ # `topics`; indicates that this is a continuation of a call, and that
179
+ # the system should return the next page of data.
180
+ # @param [Integer] max Maximum number of topics to return.
181
+ #
182
+ # @return [Array<Google::Cloud::Pubsub::Topic>] (See
183
+ # {Google::Cloud::Pubsub::Topic::List})
184
+ #
185
+ # @example
186
+ # require "google/cloud"
187
+ #
188
+ # gcloud = Google::Cloud.new
189
+ # pubsub = gcloud.pubsub
190
+ #
191
+ # topics = pubsub.topics
192
+ # topics.each do |topic|
193
+ # puts topic.name
194
+ # end
195
+ #
196
+ # @example Retrieve all topics: (See {Topic::List#all})
197
+ # require "google/cloud"
198
+ #
199
+ # gcloud = Google::Cloud.new
200
+ # pubsub = gcloud.pubsub
201
+ #
202
+ # topics = pubsub.topics
203
+ # topics.all do |topic|
204
+ # puts topic.name
205
+ # end
206
+ #
207
+ def topics token: nil, max: nil
208
+ ensure_service!
209
+ options = { token: token, max: max }
210
+ grpc = service.list_topics options
211
+ Topic::List.from_grpc grpc, service, max
212
+ end
213
+ alias_method :find_topics, :topics
214
+ alias_method :list_topics, :topics
215
+
216
+ ##
217
+ # Publishes one or more messages to the given topic. The topic will be
218
+ # created if the topic does previously not exist and the `autocreate`
219
+ # option is provided.
220
+ #
221
+ # A note about auto-creating the topic: Any message published to a topic
222
+ # without a subscription will be lost.
223
+ #
224
+ # @param [String] topic_name Name of a topic.
225
+ # @param [String, File] data The message data.
226
+ # @param [Hash] attributes Optional attributes for the message.
227
+ # @option attributes [Boolean] :autocreate Flag to control whether the
228
+ # provided topic will be created if it does not exist.
229
+ # @yield [publisher] a block for publishing multiple messages in one
230
+ # request
231
+ # @yieldparam [Topic::Publisher] publisher the topic publisher object
232
+ #
233
+ # @return [Message, Array<Message>] Returns the published message when
234
+ # called without a block, or an array of messages when called with a
235
+ # block.
236
+ #
237
+ # @example
238
+ # require "google/cloud"
239
+ #
240
+ # gcloud = Google::Cloud.new
241
+ # pubsub = gcloud.pubsub
242
+ #
243
+ # msg = pubsub.publish "my-topic", "new-message"
244
+ #
245
+ # @example A message can be published using a File object:
246
+ # require "google/cloud"
247
+ #
248
+ # gcloud = Google::Cloud.new
249
+ # pubsub = gcloud.pubsub
250
+ #
251
+ # msg = pubsub.publish "my-topic", File.open("message.txt")
252
+ #
253
+ # @example Additionally, a message can be published with attributes:
254
+ # require "google/cloud"
255
+ #
256
+ # gcloud = Google::Cloud.new
257
+ # pubsub = gcloud.pubsub
258
+ #
259
+ # msg = pubsub.publish "my-topic", "new-message", foo: :bar,
260
+ # this: :that
261
+ #
262
+ # @example Multiple messages can be sent at the same time using a block:
263
+ # require "google/cloud"
264
+ #
265
+ # gcloud = Google::Cloud.new
266
+ # pubsub = gcloud.pubsub
267
+ #
268
+ # msgs = pubsub.publish "my-topic" do |p|
269
+ # p.publish "new-message-1", foo: :bar
270
+ # p.publish "new-message-2", foo: :baz
271
+ # p.publish "new-message-3", foo: :bif
272
+ # end
273
+ #
274
+ # @example With `autocreate`:
275
+ # require "google/cloud"
276
+ #
277
+ # gcloud = Google::Cloud.new
278
+ # pubsub = gcloud.pubsub
279
+ #
280
+ # msg = pubsub.publish "new-topic", "new-message", autocreate: true
281
+ #
282
+ def publish topic_name, data = nil, attributes = {}
283
+ # Fix parameters
284
+ if data.is_a?(::Hash) && attributes.empty?
285
+ attributes = data
286
+ data = nil
287
+ end
288
+ # extract autocreate option
289
+ autocreate = attributes.delete :autocreate
290
+ ensure_service!
291
+ publisher = Topic::Publisher.new data, attributes
292
+ yield publisher if block_given?
293
+ return nil if publisher.messages.count.zero?
294
+ publish_batch_messages topic_name, publisher, autocreate
295
+ end
296
+
297
+ ##
298
+ # Creates a new {Subscription} object for the provided topic. The topic
299
+ # will be created if the topic does previously not exist and the
300
+ # `autocreate` option is provided.
301
+ #
302
+ # @param [String] topic_name Name of a topic.
303
+ # @param [String] subscription_name Name of the new subscription. Must
304
+ # start with a letter, and contain only letters ([A-Za-z]), numbers
305
+ # ([0-9], dashes (-), underscores (_), periods (.), tildes (~), plus
306
+ # (+) or percent signs (%). It must be between 3 and 255 characters in
307
+ # length, and it must not start with "goog".
308
+ # @param [Integer] deadline The maximum number of seconds after a
309
+ # subscriber receives a message before the subscriber should
310
+ # acknowledge the message.
311
+ # @param [String] endpoint A URL locating the endpoint to which messages
312
+ # should be pushed.
313
+ # @param [String] autocreate Flag to control whether the topic will be
314
+ # created if it does not exist.
315
+ #
316
+ # @return [Google::Cloud::Pubsub::Subscription]
317
+ #
318
+ # @example
319
+ # require "google/cloud"
320
+ #
321
+ # gcloud = Google::Cloud.new
322
+ # pubsub = gcloud.pubsub
323
+ #
324
+ # sub = pubsub.subscribe "my-topic", "my-topic-sub"
325
+ # puts sub.name # => "my-topic-sub"
326
+ #
327
+ # @example The name is optional, and will be generated if not given.
328
+ # require "google/cloud"
329
+ #
330
+ # gcloud = Google::Cloud.new
331
+ # pubsub = gcloud.pubsub
332
+ #
333
+ # sub = pubsub.subscribe "my-topic"
334
+ # puts sub.name # => "generated-sub-name"
335
+ #
336
+ # @example Wait 2 minutes for acknowledgement and push all to endpoint:
337
+ # require "google/cloud"
338
+ #
339
+ # gcloud = Google::Cloud.new
340
+ # pubsub = gcloud.pubsub
341
+ #
342
+ # sub = pubsub.subscribe "my-topic", "my-topic-sub",
343
+ # deadline: 120,
344
+ # endpoint: "https://example.com/push"
345
+ #
346
+ # @example With `autocreate`:
347
+ # require "google/cloud"
348
+ #
349
+ # gcloud = Google::Cloud.new
350
+ # pubsub = gcloud.pubsub
351
+ #
352
+ # sub = pubsub.subscribe "new-topic", "new-topic-sub",
353
+ # autocreate: true
354
+ #
355
+ def subscribe topic_name, subscription_name, deadline: nil,
356
+ endpoint: nil, autocreate: nil
357
+ ensure_service!
358
+ options = { deadline: deadline, endpoint: endpoint }
359
+ grpc = service.create_subscription topic_name,
360
+ subscription_name, options
361
+ Subscription.from_grpc grpc, service
362
+ rescue Google::Cloud::NotFoundError => e
363
+ if autocreate
364
+ create_topic topic_name
365
+ return subscribe(topic_name, subscription_name,
366
+ deadline: deadline, endpoint: endpoint,
367
+ autocreate: false)
368
+ end
369
+ raise e
370
+ end
371
+ alias_method :create_subscription, :subscribe
372
+ alias_method :new_subscription, :subscribe
373
+
374
+ ##
375
+ # Retrieves subscription by name.
376
+ #
377
+ # @param [String] subscription_name Name of a subscription.
378
+ # @param [String] project If the subscription belongs to a project other
379
+ # than the one currently connected to, the alternate project ID can be
380
+ # specified here.
381
+ # @param [Boolean] skip_lookup Optionally create a {Subscription} object
382
+ # without verifying the subscription resource exists on the Pub/Sub
383
+ # service. Calls made on this object will raise errors if the service
384
+ # resource does not exist. Default is `false`.
385
+ #
386
+ # @return [Google::Cloud::Pubsub::Subscription, nil] Returns `nil` if
387
+ # the subscription does not exist
388
+ #
389
+ # @example
390
+ # require "google/cloud"
391
+ #
392
+ # gcloud = Google::Cloud.new
393
+ # pubsub = gcloud.pubsub
394
+ #
395
+ # subscription = pubsub.subscription "my-sub"
396
+ # puts subscription.name
397
+ #
398
+ # @example Skip the lookup against the service with `skip_lookup`:
399
+ # require "google/cloud"
400
+ #
401
+ # gcloud = Google::Cloud.new
402
+ # pubsub = gcloud.pubsub
403
+ #
404
+ # # No API call is made to retrieve the subscription information.
405
+ # subscription = pubsub.subscription "my-sub", skip_lookup: true
406
+ # puts subscription.name
407
+ #
408
+ def subscription subscription_name, project: nil, skip_lookup: nil
409
+ ensure_service!
410
+ options = { project: project }
411
+ if skip_lookup
412
+ return Subscription.new_lazy subscription_name, service, options
413
+ end
414
+ grpc = service.get_subscription subscription_name
415
+ Subscription.from_grpc grpc, service
416
+ rescue Google::Cloud::NotFoundError
417
+ nil
418
+ end
419
+ alias_method :get_subscription, :subscription
420
+ alias_method :find_subscription, :subscription
421
+
422
+ ##
423
+ # Retrieves a list of subscriptions for the given project.
424
+ #
425
+ # @param [String] token A previously-returned page token representing
426
+ # part of the larger set of results to view.
427
+ # @param [Integer] max Maximum number of subscriptions to return.
428
+ #
429
+ # @return [Array<Google::Cloud::Pubsub::Subscription>] (See
430
+ # {Google::Cloud::Pubsub::Subscription::List})
431
+ #
432
+ # @example
433
+ # require "google/cloud"
434
+ #
435
+ # gcloud = Google::Cloud.new
436
+ # pubsub = gcloud.pubsub
437
+ #
438
+ # subscriptions = pubsub.subscriptions
439
+ # subscriptions.each do |subscription|
440
+ # puts subscription.name
441
+ # end
442
+ #
443
+ # @example Retrieve all subscriptions: (See {Subscription::List#all})
444
+ # require "google/cloud"
445
+ #
446
+ # gcloud = Google::Cloud.new
447
+ # pubsub = gcloud.pubsub
448
+ #
449
+ # subscriptions = pubsub.subscriptions
450
+ # subscriptions.all do |subscription|
451
+ # puts subscription.name
452
+ # end
453
+ #
454
+ def subscriptions token: nil, max: nil
455
+ ensure_service!
456
+ options = { token: token, max: max }
457
+ grpc = service.list_subscriptions options
458
+ Subscription::List.from_grpc grpc, service, max
459
+ end
460
+ alias_method :find_subscriptions, :subscriptions
461
+ alias_method :list_subscriptions, :subscriptions
462
+
463
+ protected
464
+
465
+ ##
466
+ # @private Raise an error unless an active connection to the service is
467
+ # available.
468
+ def ensure_service!
469
+ fail "Must have active connection to service" unless service
470
+ end
471
+
472
+ ##
473
+ # Call the publish API with arrays of data data and attrs.
474
+ def publish_batch_messages topic_name, batch, autocreate = false
475
+ grpc = service.publish topic_name, batch.messages
476
+ batch.to_gcloud_messages Array(grpc.message_ids)
477
+ rescue Google::Cloud::NotFoundError => e
478
+ if autocreate
479
+ create_topic topic_name
480
+ return publish_batch_messages topic_name, batch, false
481
+ end
482
+ raise e
483
+ end
484
+ end
485
+ end
486
+ end
487
+ end