gcloud 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/AUTHENTICATION.md +1 -1
- data/CHANGELOG.md +14 -0
- data/OVERVIEW.md +87 -0
- data/lib/gcloud.rb +106 -0
- data/lib/gcloud/credentials.rb +1 -1
- data/lib/gcloud/datastore.rb +44 -31
- data/lib/gcloud/datastore/credentials.rb +1 -1
- data/lib/gcloud/datastore/dataset.rb +20 -14
- data/lib/gcloud/datastore/entity.rb +25 -18
- data/lib/gcloud/datastore/key.rb +11 -8
- data/lib/gcloud/pubsub.rb +375 -0
- data/lib/gcloud/pubsub/connection.rb +284 -0
- data/lib/gcloud/pubsub/credentials.rb +29 -0
- data/lib/gcloud/pubsub/errors.rb +91 -0
- data/lib/gcloud/pubsub/message.rb +90 -0
- data/lib/gcloud/pubsub/project.rb +408 -0
- data/lib/gcloud/pubsub/received_message.rb +170 -0
- data/lib/gcloud/pubsub/subscription.rb +605 -0
- data/lib/gcloud/pubsub/subscription/list.rb +50 -0
- data/lib/gcloud/pubsub/topic.rb +640 -0
- data/lib/gcloud/pubsub/topic/list.rb +46 -0
- data/lib/gcloud/storage.rb +84 -66
- data/lib/gcloud/storage/bucket.rb +87 -68
- data/lib/gcloud/storage/bucket/acl.rb +140 -105
- data/lib/gcloud/storage/credentials.rb +1 -1
- data/lib/gcloud/storage/errors.rb +8 -0
- data/lib/gcloud/storage/file.rb +138 -78
- data/lib/gcloud/storage/file/acl.rb +98 -80
- data/lib/gcloud/storage/project.rb +42 -32
- data/lib/gcloud/version.rb +1 -1
- metadata +16 -9
- data/CONTRIBUTING.md +0 -93
- data/LICENSE +0 -201
- data/README.md +0 -110
@@ -0,0 +1,50 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Gcloud
|
17
|
+
module Pubsub
|
18
|
+
class Subscription
|
19
|
+
##
|
20
|
+
# Subscription::List is a special case Array with additional values.
|
21
|
+
class List < DelegateClass(::Array)
|
22
|
+
##
|
23
|
+
# If not empty, indicates that there are more subscriptions
|
24
|
+
# that match the request and this value should be passed to
|
25
|
+
# the next Gcloud::PubSub::Topic#subscriptions to continue.
|
26
|
+
attr_accessor :token
|
27
|
+
|
28
|
+
##
|
29
|
+
# Create a new Subscription::List with an array of values.
|
30
|
+
def initialize arr = [], token = nil
|
31
|
+
super arr
|
32
|
+
@token = token
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# New Subscription::List from a response object.
|
37
|
+
def self.from_resp resp, conn #:nodoc:
|
38
|
+
subs = Array(resp.data["subscriptions"]).map do |gapi_object|
|
39
|
+
if gapi_object.is_a? String
|
40
|
+
Subscription.new_lazy gapi_object, conn
|
41
|
+
else
|
42
|
+
Subscription.from_gapi gapi_object, conn
|
43
|
+
end
|
44
|
+
end
|
45
|
+
new subs, resp.data["nextPageToken"]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,640 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "json"
|
17
|
+
require "gcloud/pubsub/errors"
|
18
|
+
require "gcloud/pubsub/topic/list"
|
19
|
+
require "gcloud/pubsub/subscription"
|
20
|
+
|
21
|
+
module Gcloud
|
22
|
+
module Pubsub
|
23
|
+
##
|
24
|
+
# = Topic
|
25
|
+
#
|
26
|
+
# A named resource to which messages are published.
|
27
|
+
#
|
28
|
+
# require "gcloud"
|
29
|
+
#
|
30
|
+
# gcloud = Gcloud.new
|
31
|
+
# pubsub = gcloud.pubsub
|
32
|
+
#
|
33
|
+
# topic = pubsub.topic "my-topic"
|
34
|
+
# topic.publish "task completed"
|
35
|
+
#
|
36
|
+
class Topic
|
37
|
+
##
|
38
|
+
# The Connection object.
|
39
|
+
attr_accessor :connection #:nodoc:
|
40
|
+
|
41
|
+
##
|
42
|
+
# The Google API Client object.
|
43
|
+
attr_accessor :gapi #:nodoc:
|
44
|
+
|
45
|
+
##
|
46
|
+
# Create an empty Topic object.
|
47
|
+
def initialize #:nodoc:
|
48
|
+
@connection = nil
|
49
|
+
@gapi = {}
|
50
|
+
@name = nil
|
51
|
+
@autocreate = nil
|
52
|
+
@exists = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# New lazy Topic object without making an HTTP request.
|
57
|
+
def self.new_lazy name, conn, options = {} #:nodoc:
|
58
|
+
options[:autocreate] = true if options[:autocreate].nil?
|
59
|
+
new.tap do |t|
|
60
|
+
t.gapi = nil
|
61
|
+
t.connection = conn
|
62
|
+
t.instance_eval do
|
63
|
+
@name = conn.topic_path(name, options)
|
64
|
+
@autocreate = options[:autocreate]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# The name of the topic in the form of
|
71
|
+
# "/projects/project-identifier/topics/topic-name".
|
72
|
+
def name
|
73
|
+
@gapi ? @gapi["name"] : @name
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Permanently deletes the topic.
|
78
|
+
#
|
79
|
+
# === Returns
|
80
|
+
#
|
81
|
+
# +true+ if the topic was deleted.
|
82
|
+
#
|
83
|
+
# === Example
|
84
|
+
#
|
85
|
+
# require "gcloud"
|
86
|
+
#
|
87
|
+
# gcloud = Gcloud.new
|
88
|
+
# pubsub = gcloud.pubsub
|
89
|
+
#
|
90
|
+
# topic = pubsub.topic "my-topic"
|
91
|
+
# topic.delete
|
92
|
+
#
|
93
|
+
def delete
|
94
|
+
ensure_connection!
|
95
|
+
resp = connection.delete_topic name
|
96
|
+
if resp.success?
|
97
|
+
true
|
98
|
+
else
|
99
|
+
fail ApiError.from_response(resp)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Creates a new Subscription object on the current Topic.
|
105
|
+
#
|
106
|
+
# === Parameters
|
107
|
+
#
|
108
|
+
# +subscription_name+::
|
109
|
+
# Name of the new subscription. Must start with a letter, and contain
|
110
|
+
# only letters ([A-Za-z]), numbers ([0-9], dashes (-), underscores (_),
|
111
|
+
# periods (.), tildes (~), plus (+) or percent signs (%). It must be
|
112
|
+
# between 3 and 255 characters in length, and it must not start with
|
113
|
+
# "goog". (+String+)
|
114
|
+
# +options+::
|
115
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
116
|
+
# <code>options[:deadline]</code>::
|
117
|
+
# The maximum number of seconds after a subscriber receives a message
|
118
|
+
# before the subscriber should acknowledge the message. (+Integer+)
|
119
|
+
# <code>options[:endpoint]</code>::
|
120
|
+
# A URL locating the endpoint to which messages should be pushed.
|
121
|
+
# e.g. "https://example.com/push" (+String+)
|
122
|
+
#
|
123
|
+
# === Returns
|
124
|
+
#
|
125
|
+
# Gcloud::Pubsub::Subscription
|
126
|
+
#
|
127
|
+
# === Examples
|
128
|
+
#
|
129
|
+
# require "gcloud"
|
130
|
+
#
|
131
|
+
# gcloud = Gcloud.new
|
132
|
+
# pubsub = gcloud.pubsub
|
133
|
+
#
|
134
|
+
# topic = pubsub.topic "my-topic"
|
135
|
+
# sub = topic.subscribe "my-topic-sub"
|
136
|
+
# puts sub.name # => "my-topic-sub"
|
137
|
+
#
|
138
|
+
# The name is optional, and will be generated if not given.
|
139
|
+
#
|
140
|
+
# require "gcloud"
|
141
|
+
#
|
142
|
+
# gcloud = Gcloud.new
|
143
|
+
# pubsub = gcloud.pubsub
|
144
|
+
#
|
145
|
+
# topic = pubsub.topic "my-topic"
|
146
|
+
# sub = topic.subscribe "my-topic-sub"
|
147
|
+
# puts sub.name # => "generated-sub-name"
|
148
|
+
#
|
149
|
+
# The subscription can be created that waits two minutes for
|
150
|
+
# acknowledgement and pushed all messages to an endpoint
|
151
|
+
#
|
152
|
+
# require "gcloud"
|
153
|
+
#
|
154
|
+
# gcloud = Gcloud.new
|
155
|
+
# pubsub = gcloud.pubsub
|
156
|
+
#
|
157
|
+
# topic = pubsub.topic "my-topic"
|
158
|
+
# sub = topic.subscribe "my-topic-sub",
|
159
|
+
# deadline: 120,
|
160
|
+
# endpoint: "https://example.com/push"
|
161
|
+
#
|
162
|
+
def subscribe subscription_name, options = {}
|
163
|
+
ensure_connection!
|
164
|
+
resp = connection.create_subscription name, subscription_name, options
|
165
|
+
if resp.success?
|
166
|
+
Subscription.from_gapi resp.data, connection
|
167
|
+
else
|
168
|
+
fail ApiError.from_response(resp)
|
169
|
+
end
|
170
|
+
rescue Gcloud::Pubsub::NotFoundError => e
|
171
|
+
retry if lazily_create_topic!
|
172
|
+
raise e
|
173
|
+
end
|
174
|
+
alias_method :create_subscription, :subscribe
|
175
|
+
alias_method :new_subscription, :subscribe
|
176
|
+
|
177
|
+
##
|
178
|
+
# Retrieves subscription by name.
|
179
|
+
# The difference between this method and Topic#get_subscription is
|
180
|
+
# that this method does not make an API call to Pub/Sub to verify the
|
181
|
+
# subscription exists.
|
182
|
+
#
|
183
|
+
# === Parameters
|
184
|
+
#
|
185
|
+
# +subscription_name+::
|
186
|
+
# Name of a subscription. (+String+)
|
187
|
+
#
|
188
|
+
# === Returns
|
189
|
+
#
|
190
|
+
# Gcloud::Pubsub::Subscription
|
191
|
+
#
|
192
|
+
# === Example
|
193
|
+
#
|
194
|
+
# require "gcloud"
|
195
|
+
#
|
196
|
+
# gcloud = Gcloud.new
|
197
|
+
# pubsub = gcloud.pubsub
|
198
|
+
#
|
199
|
+
# topic = pubsub.topic "my-topic"
|
200
|
+
# subscription = topic.subscription "my-topic-subscription"
|
201
|
+
# puts subscription.name
|
202
|
+
#
|
203
|
+
def subscription subscription_name
|
204
|
+
ensure_connection!
|
205
|
+
|
206
|
+
Subscription.new_lazy subscription_name, connection
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Retrieves a subscription by name.
|
211
|
+
# The difference between this method and Topic#subscription is that
|
212
|
+
# this method makes an API call to Pub/Sub to verify the subscription
|
213
|
+
# exists.
|
214
|
+
#
|
215
|
+
# === Parameters
|
216
|
+
#
|
217
|
+
# +subscription_name+::
|
218
|
+
# Name of a subscription. (+String+)
|
219
|
+
#
|
220
|
+
# === Returns
|
221
|
+
#
|
222
|
+
# Gcloud::Pubsub::Subscription or nil if subscription does not exist
|
223
|
+
#
|
224
|
+
# === Example
|
225
|
+
#
|
226
|
+
# require "gcloud"
|
227
|
+
#
|
228
|
+
# gcloud = Gcloud.new
|
229
|
+
# pubsub = gcloud.pubsub
|
230
|
+
#
|
231
|
+
# topic = pubsub.topic "my-topic"
|
232
|
+
# subscription = topic.get_subscription "my-topic-subscription"
|
233
|
+
# puts subscription.name
|
234
|
+
#
|
235
|
+
def get_subscription subscription_name
|
236
|
+
ensure_connection!
|
237
|
+
resp = connection.get_subscription subscription_name
|
238
|
+
if resp.success?
|
239
|
+
Subscription.from_gapi resp.data, connection
|
240
|
+
else
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
alias_method :find_subscription, :get_subscription
|
245
|
+
|
246
|
+
##
|
247
|
+
# Retrieves a list of subscription names for the given project.
|
248
|
+
#
|
249
|
+
# === Parameters
|
250
|
+
#
|
251
|
+
# +options+::
|
252
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
253
|
+
# <code>options[:token]</code>::
|
254
|
+
# The +token+ value returned by the last call to +subscriptions+;
|
255
|
+
# indicates that this is a continuation of a call, and that the system
|
256
|
+
# should return the next page of data. (+String+)
|
257
|
+
# <code>options[:max]</code>::
|
258
|
+
# Maximum number of subscriptions to return. (+Integer+)
|
259
|
+
#
|
260
|
+
# === Returns
|
261
|
+
#
|
262
|
+
# Array of Subscription objects (Subscription::List)
|
263
|
+
#
|
264
|
+
# === Examples
|
265
|
+
#
|
266
|
+
# require "gcloud"
|
267
|
+
#
|
268
|
+
# gcloud = Gcloud.new
|
269
|
+
# pubsub = gcloud.pubsub
|
270
|
+
#
|
271
|
+
# topic = pubsub.topic "my-topic"
|
272
|
+
# subscription = topic.subscriptions
|
273
|
+
# subscriptions.each do |subscription|
|
274
|
+
# puts subscription.name
|
275
|
+
# end
|
276
|
+
#
|
277
|
+
# If you have a significant number of subscriptions, you may need to
|
278
|
+
# paginate through them: (See Subscription::List#token)
|
279
|
+
#
|
280
|
+
# require "gcloud"
|
281
|
+
#
|
282
|
+
# gcloud = Gcloud.new
|
283
|
+
# pubsub = gcloud.pubsub
|
284
|
+
#
|
285
|
+
# topic = pubsub.topic "my-topic"
|
286
|
+
# all_subs = []
|
287
|
+
# tmp_subs = topic.subscriptions
|
288
|
+
# while tmp_subs.any? do
|
289
|
+
# tmp_subs.each do |subscription|
|
290
|
+
# all_subs << subscription
|
291
|
+
# end
|
292
|
+
# # break loop if no more subscriptions available
|
293
|
+
# break if tmp_subs.token.nil?
|
294
|
+
# # get the next group of subscriptions
|
295
|
+
# tmp_subs = topic.subscriptions token: tmp_subs.token
|
296
|
+
# end
|
297
|
+
#
|
298
|
+
def subscriptions options = {}
|
299
|
+
ensure_connection!
|
300
|
+
resp = connection.list_topics_subscriptions name, options
|
301
|
+
if resp.success?
|
302
|
+
Subscription::List.from_resp resp, connection
|
303
|
+
else
|
304
|
+
fail ApiError.from_response(resp)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
alias_method :find_subscriptions, :subscriptions
|
308
|
+
alias_method :list_subscriptions, :subscriptions
|
309
|
+
|
310
|
+
##
|
311
|
+
# Publishes one or more messages to the topic.
|
312
|
+
#
|
313
|
+
# === Parameters
|
314
|
+
#
|
315
|
+
# +data+::
|
316
|
+
# The message data. (+String+)
|
317
|
+
# +attributes+::
|
318
|
+
# Optional attributes for the message. (+Hash+)
|
319
|
+
#
|
320
|
+
# === Returns
|
321
|
+
#
|
322
|
+
# Message object when called without a block,
|
323
|
+
# Array of Message objects when called with a block
|
324
|
+
#
|
325
|
+
# === Examples
|
326
|
+
#
|
327
|
+
# require "gcloud"
|
328
|
+
#
|
329
|
+
# gcloud = Gcloud.new
|
330
|
+
# pubsub = gcloud.pubsub
|
331
|
+
#
|
332
|
+
# topic = pubsub.topic "my-topic"
|
333
|
+
# msg = topic.publish "new-message"
|
334
|
+
#
|
335
|
+
# Additionally, a message can be published with attributes:
|
336
|
+
#
|
337
|
+
# require "gcloud"
|
338
|
+
#
|
339
|
+
# gcloud = Gcloud.new
|
340
|
+
# pubsub = gcloud.pubsub
|
341
|
+
#
|
342
|
+
# topic = pubsub.topic "my-topic"
|
343
|
+
# msg = topic.publish "new-message",
|
344
|
+
# foo: :bar,
|
345
|
+
# this: :that
|
346
|
+
#
|
347
|
+
# Multiple messages can be published at the same time by passing a block:
|
348
|
+
#
|
349
|
+
# require "gcloud"
|
350
|
+
#
|
351
|
+
# gcloud = Gcloud.new
|
352
|
+
# pubsub = gcloud.pubsub
|
353
|
+
#
|
354
|
+
# topic = pubsub.topic "my-topic"
|
355
|
+
# msgs = topic.publish do |batch|
|
356
|
+
# batch.publish "new-message-1", foo: :bar
|
357
|
+
# batch.publish "new-message-2", foo: :baz
|
358
|
+
# batch.publish "new-message-3", foo: :bif
|
359
|
+
# end
|
360
|
+
#
|
361
|
+
def publish data = nil, attributes = {}
|
362
|
+
ensure_connection!
|
363
|
+
batch = Batch.new data, attributes
|
364
|
+
yield batch if block_given?
|
365
|
+
return nil if batch.messages.count.zero?
|
366
|
+
publish_batch_messages batch
|
367
|
+
rescue Gcloud::Pubsub::NotFoundError => e
|
368
|
+
retry if lazily_create_topic!
|
369
|
+
raise e
|
370
|
+
end
|
371
|
+
|
372
|
+
##
|
373
|
+
# Gets the access control policy.
|
374
|
+
#
|
375
|
+
# === Parameters
|
376
|
+
#
|
377
|
+
# +options+::
|
378
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
379
|
+
# <code>options[:force]</code>::
|
380
|
+
# Force the latest policy to be retrieved from the Pub/Sub service when
|
381
|
+
# +true. Otherwise the policy will be memoized to reduce the number of
|
382
|
+
# API calls made to the Pub/Sub service. The default is +false+.
|
383
|
+
# (+Boolean+)
|
384
|
+
#
|
385
|
+
# === Returns
|
386
|
+
#
|
387
|
+
# A hash that conforms to the following structure:
|
388
|
+
#
|
389
|
+
# {
|
390
|
+
# "bindings" => [{
|
391
|
+
# "role" => "roles/viewer",
|
392
|
+
# "members" => ["serviceAccount:your-service-account"]
|
393
|
+
# }],
|
394
|
+
# "rules" => []
|
395
|
+
# }
|
396
|
+
#
|
397
|
+
# === Examples
|
398
|
+
#
|
399
|
+
# By default, the policy values are memoized to reduce the number of API
|
400
|
+
# calls to the Pub/Sub service.
|
401
|
+
#
|
402
|
+
# require "gcloud"
|
403
|
+
#
|
404
|
+
# gcloud = Gcloud.new
|
405
|
+
# pubsub = gcloud.pubsub
|
406
|
+
#
|
407
|
+
# topic = pubsub.topic "my-topic"
|
408
|
+
# puts topic.policy["bindings"]
|
409
|
+
# puts topic.policy["rules"]
|
410
|
+
#
|
411
|
+
# To retrieve the latest policy from the Pub/Sub service, use the +force+
|
412
|
+
# flag.
|
413
|
+
#
|
414
|
+
# require "gcloud"
|
415
|
+
#
|
416
|
+
# gcloud = Gcloud.new
|
417
|
+
# pubsub = gcloud.pubsub
|
418
|
+
#
|
419
|
+
# topic = pubsub.topic "my-topic"
|
420
|
+
# policy = topic.policy force: true
|
421
|
+
#
|
422
|
+
def policy options = {}
|
423
|
+
@policy = nil if options[:force]
|
424
|
+
@policy ||= begin
|
425
|
+
ensure_connection!
|
426
|
+
resp = connection.get_topic_policy name
|
427
|
+
policy = resp.data["policy"]
|
428
|
+
policy = policy.to_hash if policy.respond_to? :to_hash
|
429
|
+
policy
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
##
|
434
|
+
# Sets the access control policy.
|
435
|
+
#
|
436
|
+
# === Parameters
|
437
|
+
#
|
438
|
+
# +new_policy+::
|
439
|
+
# A hash that conforms to the following structure:
|
440
|
+
#
|
441
|
+
# {
|
442
|
+
# "bindings" => [{
|
443
|
+
# "role" => "roles/viewer",
|
444
|
+
# "members" => ["serviceAccount:your-service-account"]
|
445
|
+
# }],
|
446
|
+
# "rules" => []
|
447
|
+
# }
|
448
|
+
#
|
449
|
+
# === Example
|
450
|
+
#
|
451
|
+
# require "gcloud"
|
452
|
+
#
|
453
|
+
# gcloud = Gcloud.new
|
454
|
+
# pubsub = gcloud.pubsub
|
455
|
+
#
|
456
|
+
# viewer_policy = {
|
457
|
+
# "bindings" => [{
|
458
|
+
# "role" => "roles/viewer",
|
459
|
+
# "members" => ["serviceAccount:your-service-account"]
|
460
|
+
# }]
|
461
|
+
# }
|
462
|
+
# topic = pubsub.topic "my-topic"
|
463
|
+
# topic.policy = viewer_policy
|
464
|
+
#
|
465
|
+
def policy= new_policy
|
466
|
+
ensure_connection!
|
467
|
+
resp = connection.set_topic_policy name, new_policy
|
468
|
+
if resp.success?
|
469
|
+
@policy = resp.data["policy"]
|
470
|
+
@policy = @policy.to_hash if @policy.respond_to? :to_hash
|
471
|
+
else
|
472
|
+
fail ApiError.from_response(resp)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
##
|
477
|
+
# Determines whether the topic exists in the Pub/Sub service.
|
478
|
+
#
|
479
|
+
# === Example
|
480
|
+
#
|
481
|
+
# require "gcloud"
|
482
|
+
#
|
483
|
+
# gcloud = Gcloud.new
|
484
|
+
# pubsub = gcloud.pubsub
|
485
|
+
#
|
486
|
+
# topic = pubsub.topic "my-topic"
|
487
|
+
# topic.exists? #=> true
|
488
|
+
#
|
489
|
+
def exists?
|
490
|
+
# Always true if we have a gapi object
|
491
|
+
return true unless @gapi.nil?
|
492
|
+
# If we have a value, return it
|
493
|
+
return @exists unless @exists.nil?
|
494
|
+
ensure_gapi!
|
495
|
+
@exists = !@gapi.nil?
|
496
|
+
end
|
497
|
+
|
498
|
+
##
|
499
|
+
# Determines whether the topic object was created with an HTTP call.
|
500
|
+
#
|
501
|
+
# === Example
|
502
|
+
#
|
503
|
+
# require "gcloud"
|
504
|
+
#
|
505
|
+
# gcloud = Gcloud.new
|
506
|
+
# pubsub = gcloud.pubsub
|
507
|
+
#
|
508
|
+
# topic = pubsub.topic "my-topic"
|
509
|
+
# topic.lazy? #=> false
|
510
|
+
#
|
511
|
+
def lazy? #:nodoc:
|
512
|
+
@gapi.nil?
|
513
|
+
end
|
514
|
+
|
515
|
+
##
|
516
|
+
# Determines whether the lazy topic object should create a topic on the
|
517
|
+
# Pub/Sub service.
|
518
|
+
#
|
519
|
+
# === Example
|
520
|
+
#
|
521
|
+
# require "gcloud"
|
522
|
+
#
|
523
|
+
# gcloud = Gcloud.new
|
524
|
+
# pubsub = gcloud.pubsub
|
525
|
+
#
|
526
|
+
# topic = pubsub.topic "my-topic"
|
527
|
+
# topic.autocreate? #=> true
|
528
|
+
#
|
529
|
+
def autocreate? #:nodoc:
|
530
|
+
@autocreate
|
531
|
+
end
|
532
|
+
|
533
|
+
##
|
534
|
+
# New Topic from a Google API Client object.
|
535
|
+
def self.from_gapi gapi, conn #:nodoc:
|
536
|
+
new.tap do |f|
|
537
|
+
f.gapi = gapi
|
538
|
+
f.connection = conn
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
protected
|
543
|
+
|
544
|
+
##
|
545
|
+
# Raise an error unless an active connection is available.
|
546
|
+
def ensure_connection!
|
547
|
+
fail "Must have active connection" unless connection
|
548
|
+
end
|
549
|
+
|
550
|
+
##
|
551
|
+
# Ensures a Google API object exists.
|
552
|
+
def ensure_gapi!
|
553
|
+
ensure_connection!
|
554
|
+
return @gapi if @gapi
|
555
|
+
resp = connection.get_topic @name
|
556
|
+
@gapi = resp.data if resp.success?
|
557
|
+
end
|
558
|
+
|
559
|
+
##
|
560
|
+
def lazily_create_topic!
|
561
|
+
if lazy? && autocreate?
|
562
|
+
resp = connection.create_topic name
|
563
|
+
if resp.success?
|
564
|
+
@gapi = resp.data
|
565
|
+
return true
|
566
|
+
end
|
567
|
+
end
|
568
|
+
nil
|
569
|
+
end
|
570
|
+
|
571
|
+
##
|
572
|
+
# Call the publish API with arrays of data data and attrs.
|
573
|
+
def publish_batch_messages batch
|
574
|
+
resp = connection.publish name, batch.messages
|
575
|
+
if resp.success?
|
576
|
+
batch.to_gcloud_messages resp.data["messageIds"]
|
577
|
+
else
|
578
|
+
fail ApiError.from_response(resp)
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
##
|
583
|
+
# Batch object used to publish multiple messages at once.
|
584
|
+
class Batch
|
585
|
+
##
|
586
|
+
# The messages to publish
|
587
|
+
attr_reader :messages #:nodoc:
|
588
|
+
|
589
|
+
##
|
590
|
+
# Create a new instance of the object.
|
591
|
+
def initialize data = nil, attributes = {} #:nodoc:
|
592
|
+
@messages = []
|
593
|
+
@mode = :batch
|
594
|
+
return if data.nil?
|
595
|
+
@mode = :single
|
596
|
+
publish data, attributes
|
597
|
+
end
|
598
|
+
|
599
|
+
##
|
600
|
+
# Add multiple messages to the topic.
|
601
|
+
# All messages added will be published at once.
|
602
|
+
# See Gcloud::Pubsub::Topic#publish
|
603
|
+
def publish data, attributes = {}
|
604
|
+
@messages << [data, attributes]
|
605
|
+
end
|
606
|
+
|
607
|
+
##
|
608
|
+
# Create Message objects with message ids.
|
609
|
+
def to_gcloud_messages message_ids #:nodoc:
|
610
|
+
msgs = @messages.zip(Array(message_ids)).map do |arr, id|
|
611
|
+
Message.from_gapi "data" => arr[0],
|
612
|
+
"attributes" => jsonify_hash(arr[1]),
|
613
|
+
"messageId" => id
|
614
|
+
end
|
615
|
+
# Return just one Message if a single publish,
|
616
|
+
# otherwise return the array of Messages.
|
617
|
+
if @mode == :single && msgs.count <= 1
|
618
|
+
msgs.first
|
619
|
+
else
|
620
|
+
msgs
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
protected
|
625
|
+
|
626
|
+
##
|
627
|
+
# Make the hash look like it was returned from the Cloud API.
|
628
|
+
def jsonify_hash hash
|
629
|
+
if hash.respond_to? :to_h
|
630
|
+
hash = hash.to_h
|
631
|
+
else
|
632
|
+
hash = Hash.try_convert(hash) || {}
|
633
|
+
end
|
634
|
+
return hash if hash.empty?
|
635
|
+
JSON.parse(JSON.dump(hash))
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
end
|
640
|
+
end
|