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.
@@ -0,0 +1,408 @@
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 "gcloud/pubsub/connection"
17
+ require "gcloud/pubsub/credentials"
18
+ require "gcloud/pubsub/errors"
19
+ require "gcloud/pubsub/topic"
20
+
21
+ module Gcloud
22
+ module Pubsub
23
+ ##
24
+ # = Project
25
+ #
26
+ # Represents the project that pubsub messages are pushed to and pulled from.
27
+ # Topic is a named resource to which messages are sent by publishers.
28
+ # Subscription is a named resource representing the stream of messages from
29
+ # a single, specific topic, to be delivered to the subscribing application.
30
+ # Message is a combination of data and attributes that a publisher sends to
31
+ # a topic and is eventually delivered to subscribers.
32
+ #
33
+ # require "gcloud"
34
+ #
35
+ # gcloud = Gcloud.new
36
+ # pubsub = gcloud.pubsub
37
+ #
38
+ # topic = pubsub.topic "my-topic"
39
+ # topic.publish "task completed"
40
+ #
41
+ # See Gcloud#pubsub
42
+ class Project
43
+ ##
44
+ # The Connection object.
45
+ attr_accessor :connection #:nodoc:
46
+
47
+ ##
48
+ # Creates a new Connection instance.
49
+ def initialize project, credentials #:nodoc:
50
+ @connection = Connection.new project, credentials
51
+ end
52
+
53
+ # The Pub/Sub project connected to.
54
+ #
55
+ # === Example
56
+ #
57
+ # require "gcloud"
58
+ #
59
+ # gcloud = Gcloud.new "my-todo-project",
60
+ # "/path/to/keyfile.json"
61
+ # pubsub = gcloud.pubsub
62
+ #
63
+ # pubsub.project #=> "my-todo-project"
64
+ #
65
+ def project
66
+ connection.project
67
+ end
68
+
69
+ ##
70
+ # Default project.
71
+ def self.default_project #:nodoc:
72
+ ENV["PUBSUB_PROJECT"] || ENV["GOOGLE_CLOUD_PROJECT"]
73
+ end
74
+
75
+ ##
76
+ # Retrieves topic by name.
77
+ # The difference between this method and Project#topic is that this
78
+ # method makes an API call to Pub/Sub to verify the topic exists.
79
+ #
80
+ # === Parameters
81
+ #
82
+ # +topic_name+::
83
+ # Name of a topic. (+String+)
84
+ #
85
+ # === Returns
86
+ #
87
+ # Gcloud::Pubsub::Topic or nil if topic does not exist
88
+ #
89
+ # === Example
90
+ #
91
+ # require "gcloud"
92
+ #
93
+ # gcloud = Gcloud.new
94
+ # pubsub = gcloud.pubsub
95
+ # topic = pubsub.get_topic "my-topic"
96
+ #
97
+ def get_topic topic_name
98
+ ensure_connection!
99
+ resp = connection.get_topic topic_name
100
+ if resp.success?
101
+ Topic.from_gapi resp.data, connection
102
+ else
103
+ return nil if resp.data["error"]["code"] == 404
104
+ fail ApiError.from_response(resp)
105
+ end
106
+ end
107
+ alias_method :find_topic, :get_topic
108
+
109
+ ##
110
+ # Retrieves topic by name.
111
+ # The difference between this method and Project#get_topic is that this
112
+ # method does not make an API call to Pub/Sub to verify the topic exists.
113
+ #
114
+ # === Parameters
115
+ #
116
+ # +topic_name+::
117
+ # Name of a topic. (+String+)
118
+ # +options+::
119
+ # An optional Hash for controlling additional behavior. (+Hash+)
120
+ # <code>options[:autocreate]</code>::
121
+ # Flag to control whether the topic should be created when needed.
122
+ # The default value is +true+. (+Boolean+)
123
+ # <code>options[:project]</code>::
124
+ # If the topic belongs to a project other than the one currently
125
+ # connected to, the alternate project ID can be specified here.
126
+ # (+String+)
127
+ #
128
+ # === Returns
129
+ #
130
+ # Gcloud::Pubsub::Topic
131
+ #
132
+ # === Examples
133
+ #
134
+ # require "gcloud"
135
+ #
136
+ # gcloud = Gcloud.new
137
+ # pubsub = gcloud.pubsub
138
+ # topic = pubsub.topic "existing-topic"
139
+ # msg = topic.publish "This is the first API call to Pub/Sub."
140
+ #
141
+ # By default the topic will be created in Pub/Sub when needed.
142
+ #
143
+ # require "gcloud"
144
+ #
145
+ # gcloud = Gcloud.new
146
+ # pubsub = gcloud.pubsub
147
+ # topic = pubsub.topic "non-existing-topic"
148
+ # msg = topic.publish "This will create the topic in Pub/Sub."
149
+ #
150
+ # Setting the +autocomplete+ flag to false will not create the topic.
151
+ #
152
+ # require "gcloud"
153
+ #
154
+ # gcloud = Gcloud.new
155
+ # pubsub = gcloud.pubsub
156
+ # topic = pubsub.topic "non-existing-topic"
157
+ # msg = topic.publish "This raises." #=> Gcloud::Pubsub::NotFoundError
158
+ #
159
+ # A topic in a different project can be created using the +project+ flag.
160
+ #
161
+ # require "gcloud"
162
+ #
163
+ # gcloud = Gcloud.new
164
+ # pubsub = gcloud.pubsub
165
+ # topic = pubsub.topic "another-topic", project: "another-project"
166
+ #
167
+ def topic topic_name, options = {}
168
+ ensure_connection!
169
+
170
+ Topic.new_lazy topic_name, connection, options
171
+ end
172
+
173
+ ##
174
+ # Creates a new topic.
175
+ #
176
+ # === Parameters
177
+ #
178
+ # +topic_name+::
179
+ # Name of a topic. (+String+)
180
+ #
181
+ # === Returns
182
+ #
183
+ # Gcloud::Pubsub::Topic
184
+ #
185
+ # === Examples
186
+ #
187
+ # require "gcloud"
188
+ #
189
+ # gcloud = Gcloud.new
190
+ # pubsub = gcloud.pubsub
191
+ # topic = pubsub.create_topic "my-topic"
192
+ #
193
+ def create_topic topic_name
194
+ ensure_connection!
195
+ resp = connection.create_topic topic_name
196
+ if resp.success?
197
+ Topic.from_gapi resp.data, connection
198
+ else
199
+ fail ApiError.from_response(resp)
200
+ end
201
+ end
202
+ alias_method :new_topic, :create_topic
203
+
204
+ ##
205
+ # Retrieves a list of topics for the given project.
206
+ #
207
+ # === Parameters
208
+ #
209
+ # +options+::
210
+ # An optional Hash for controlling additional behavior. (+Hash+)
211
+ # (+String+)
212
+ # <code>options[:token]</code>::
213
+ # The +token+ value returned by the last call to +topics+; indicates
214
+ # that this is a continuation of a call, and that the system should
215
+ # return the next page of data. (+String+)
216
+ # <code>options[:max]</code>::
217
+ # Maximum number of topics to return. (+Integer+)
218
+ #
219
+ # === Returns
220
+ #
221
+ # Array of Gcloud::Pubsub::Topic (Gcloud::Pubsub::Topic::List)
222
+ #
223
+ # === Examples
224
+ #
225
+ # require "gcloud"
226
+ #
227
+ # gcloud = Gcloud.new
228
+ # pubsub = gcloud.pubsub
229
+ #
230
+ # topics = pubsub.topics
231
+ # topics.each do |topic|
232
+ # puts topic.name
233
+ # end
234
+ #
235
+ # If you have a significant number of topics, you may need to paginate
236
+ # through them: (See Topic::List#token)
237
+ #
238
+ # require "gcloud"
239
+ #
240
+ # gcloud = Gcloud.new
241
+ # pubsub = gcloud.pubsub
242
+ #
243
+ # all_topics = []
244
+ # tmp_topics = pubsub.topics
245
+ # while tmp_topics.any? do
246
+ # tmp_topics.each do |topic|
247
+ # all_topics << topic
248
+ # end
249
+ # # break loop if no more topics available
250
+ # break if tmp_topics.token.nil?
251
+ # # get the next group of topics
252
+ # tmp_topics = pubsub.topics token: tmp_topics.token
253
+ # end
254
+ #
255
+ def topics options = {}
256
+ ensure_connection!
257
+ resp = connection.list_topics options
258
+ if resp.success?
259
+ Topic::List.from_resp resp, connection
260
+ else
261
+ fail ApiError.from_response(resp)
262
+ end
263
+ end
264
+ alias_method :find_topics, :topics
265
+ alias_method :list_topics, :topics
266
+
267
+ ##
268
+ # Retrieves subscription by name.
269
+ # The difference between this method and Project#get_subscription is
270
+ # that this method does not make an API call to Pub/Sub to verify the
271
+ # subscription exists.
272
+ #
273
+ # === Parameters
274
+ #
275
+ # +subscription_name+::
276
+ # Name of a subscription. (+String+)
277
+ #
278
+ # === Returns
279
+ #
280
+ # Gcloud::Pubsub::Subscription
281
+ #
282
+ # === Example
283
+ #
284
+ # require "gcloud"
285
+ #
286
+ # gcloud = Gcloud.new
287
+ # pubsub = gcloud.pubsub
288
+ #
289
+ # subscription = pubsub.get_subscription "my-topic-subscription"
290
+ # puts subscription.name
291
+ #
292
+ def subscription subscription_name
293
+ ensure_connection!
294
+
295
+ Subscription.new_lazy subscription_name, connection
296
+ end
297
+
298
+ ##
299
+ # Retrieves subscription by name.
300
+ # The difference between this method and Project#subscription is that
301
+ # this method makes an API call to Pub/Sub to verify the subscription
302
+ # exists.
303
+ #
304
+ # === Parameters
305
+ #
306
+ # +subscription_name+::
307
+ # Name of a subscription. (+String+)
308
+ #
309
+ # === Returns
310
+ #
311
+ # Gcloud::Pubsub::Subscription or +nil+ if the subscription does not exist
312
+ #
313
+ # === Example
314
+ #
315
+ # require "gcloud"
316
+ #
317
+ # gcloud = Gcloud.new
318
+ # pubsub = gcloud.pubsub
319
+ #
320
+ # subscription = pubsub.get_subscription "my-topic-subscription"
321
+ # puts subscription.name
322
+ #
323
+ def get_subscription subscription_name
324
+ ensure_connection!
325
+ resp = connection.get_subscription subscription_name
326
+ if resp.success?
327
+ Subscription.from_gapi resp.data, connection
328
+ else
329
+ nil
330
+ end
331
+ end
332
+ alias_method :find_subscription, :get_subscription
333
+
334
+ ##
335
+ # Retrieves a list of subscriptions for the given project.
336
+ #
337
+ # === Parameters
338
+ #
339
+ # +options+::
340
+ # An optional Hash for controlling additional behavior. (+Hash+)
341
+ # <code>options[:prefix]</code>::
342
+ # Filter results to subscriptions whose names begin with this prefix.
343
+ # (+String+)
344
+ # <code>options[:token]</code>::
345
+ # A previously-returned page token representing part of the larger set
346
+ # of results to view. (+String+)
347
+ # <code>options[:max]</code>::
348
+ # Maximum number of subscriptions to return. (+Integer+)
349
+ #
350
+ # === Returns
351
+ #
352
+ # Array of Gcloud::Pubsub::Subscription
353
+ # (Gcloud::Pubsub::Subscription::List)
354
+ #
355
+ # === Examples
356
+ #
357
+ # require "gcloud"
358
+ #
359
+ # gcloud = Gcloud.new
360
+ # pubsub = gcloud.pubsub
361
+ #
362
+ # subscriptions = pubsub.subscriptions
363
+ # subscriptions.each do |subscription|
364
+ # puts subscription.name
365
+ # end
366
+ #
367
+ # If you have a significant number of subscriptions, you may need to
368
+ # paginate through them: (See Subscription::List#token)
369
+ #
370
+ # require "gcloud"
371
+ #
372
+ # gcloud = Gcloud.new
373
+ # pubsub = gcloud.pubsub
374
+ #
375
+ # all_subs = []
376
+ # tmp_subs = pubsub.subscriptions
377
+ # while tmp_subs.any? do
378
+ # tmp_subs.each do |subscription|
379
+ # all_subs << subscription
380
+ # end
381
+ # # break loop if no more subscriptions available
382
+ # break if tmp_subs.token.nil?
383
+ # # get the next group of subscriptions
384
+ # tmp_subs = pubsub.subscriptions token: tmp_subs.token
385
+ # end
386
+ #
387
+ def subscriptions options = {}
388
+ ensure_connection!
389
+ resp = connection.list_subscriptions options
390
+ if resp.success?
391
+ Subscription::List.from_resp resp, connection
392
+ else
393
+ fail ApiError.from_response(resp)
394
+ end
395
+ end
396
+ alias_method :find_subscriptions, :subscriptions
397
+ alias_method :list_subscriptions, :subscriptions
398
+
399
+ protected
400
+
401
+ ##
402
+ # Raise an error unless an active connection is available.
403
+ def ensure_connection!
404
+ fail "Must have active connection" unless connection
405
+ end
406
+ end
407
+ end
408
+ end
@@ -0,0 +1,170 @@
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 "gcloud/pubsub/errors"
17
+ require "gcloud/pubsub/message"
18
+
19
+ module Gcloud
20
+ module Pubsub
21
+ ##
22
+ # = ReceivedMessage
23
+ #
24
+ # Represents a Pub/Sub Message that can be acknowledged or delayed.
25
+ #
26
+ # require "gcloud"
27
+ #
28
+ # gcloud = Gcloud.new
29
+ # pubsub = gcloud.pubsub
30
+ #
31
+ # sub = pubsub.subscription "my-topic-sub"
32
+ # received_message = sub.pull.first
33
+ # if received_message
34
+ # puts received_message.message.data
35
+ # received_message.acknowledge!
36
+ # end
37
+ #
38
+ class ReceivedMessage
39
+ ##
40
+ # The Subscription object.
41
+ attr_accessor :subscription #:nodoc:
42
+
43
+ ##
44
+ # The Google API Client object.
45
+ attr_accessor :gapi #:nodoc:
46
+
47
+ ##
48
+ # Create an empty Subscription object.
49
+ def initialize #:nodoc:
50
+ @subscription = nil
51
+ @gapi = {}
52
+ end
53
+
54
+ ##
55
+ # The acknowledgment ID for the message.
56
+ def ack_id
57
+ @gapi["ackId"]
58
+ end
59
+
60
+ ##
61
+ # The received message.
62
+ def message
63
+ Message.from_gapi @gapi["message"]
64
+ end
65
+ alias_method :msg, :message
66
+
67
+ ##
68
+ # The received message's data.
69
+ def data
70
+ message.data
71
+ end
72
+
73
+ ##
74
+ # The received message's attributes.
75
+ def attributes
76
+ message.attributes
77
+ end
78
+
79
+ ##
80
+ # The ID of the received message, assigned by the server at publication
81
+ # time. Guaranteed to be unique within the topic.
82
+ def message_id
83
+ message.message_id
84
+ end
85
+ alias_method :msg_id, :message_id
86
+
87
+ ##
88
+ # Acknowledges receipt of the message.
89
+ #
90
+ # === Example
91
+ #
92
+ # require "gcloud"
93
+ #
94
+ # gcloud = Gcloud.new
95
+ # pubsub = gcloud.pubsub
96
+ #
97
+ # sub = pubsub.subscription "my-topic-sub"
98
+ # received_message = sub.pull.first
99
+ # if received_message
100
+ # puts received_message.message.data
101
+ # received_message.acknowledge!
102
+ # end
103
+ #
104
+ def acknowledge!
105
+ ensure_subscription!
106
+ subscription.acknowledge ack_id
107
+ end
108
+ alias_method :ack!, :acknowledge!
109
+
110
+ ##
111
+ # Modifies the acknowledge deadline for the message.
112
+ #
113
+ # This indicates that more time is needed to process the message, or to
114
+ # make the message available for redelivery.
115
+ #
116
+ # === Parameters
117
+ #
118
+ # +deadline+::
119
+ # The new ack deadline in seconds from the time this request is sent
120
+ # to the Pub/Sub system. Must be >= 0. For example, if the value is
121
+ # +10+, the new ack deadline will expire 10 seconds after the call is
122
+ # made. Specifying +0+ may immediately make the message available for
123
+ # another pull request. (+Integer+)
124
+ #
125
+ # === Example
126
+ #
127
+ # require "gcloud"
128
+ #
129
+ # gcloud = Gcloud.new
130
+ # pubsub = gcloud.pubsub
131
+ #
132
+ # sub = pubsub.subscription "my-topic-sub"
133
+ # received_message = sub.pull.first
134
+ # if received_message
135
+ # puts received_message.message.data
136
+ # # Delay for 2 minutes
137
+ # received_message.delay! 120
138
+ # end
139
+ #
140
+ def delay! new_deadline
141
+ ensure_subscription!
142
+ connection = subscription.connection
143
+ resp = connection.modify_ack_deadline subscription.name,
144
+ ack_id, new_deadline
145
+ if resp.success?
146
+ true
147
+ else
148
+ fail ApiError.from_response(resp)
149
+ end
150
+ end
151
+
152
+ ##
153
+ # New ReceivedMessage from a Google API Client object.
154
+ def self.from_gapi gapi, subscription #:nodoc:
155
+ new.tap do |f|
156
+ f.gapi = gapi
157
+ f.subscription = subscription
158
+ end
159
+ end
160
+
161
+ protected
162
+
163
+ ##
164
+ # Raise an error unless an active subscription is available.
165
+ def ensure_subscription!
166
+ fail "Must have active subscription" unless subscription
167
+ end
168
+ end
169
+ end
170
+ end