gcloud 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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