google-cloud-pubsub 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/google-cloud-pubsub.rb +122 -0
- data/lib/google/cloud/pubsub.rb +445 -0
- data/lib/google/cloud/pubsub/credentials.rb +31 -0
- data/lib/google/cloud/pubsub/message.rb +96 -0
- data/lib/google/cloud/pubsub/policy.rb +209 -0
- data/lib/google/cloud/pubsub/project.rb +487 -0
- data/lib/google/cloud/pubsub/received_message.rb +162 -0
- data/lib/google/cloud/pubsub/service.rb +340 -0
- data/lib/google/cloud/pubsub/subscription.rb +570 -0
- data/lib/google/cloud/pubsub/subscription/list.rb +210 -0
- data/lib/google/cloud/pubsub/topic.rb +515 -0
- data/lib/google/cloud/pubsub/topic/list.rb +176 -0
- data/lib/google/cloud/pubsub/topic/publisher.rb +87 -0
- data/lib/google/cloud/pubsub/version.rb +22 -0
- data/lib/google/iam/v1/iam_policy.rb +33 -0
- data/lib/google/iam/v1/iam_policy_services.rb +30 -0
- data/lib/google/iam/v1/policy.rb +25 -0
- data/lib/google/pubsub/v1/pubsub_pb.rb +129 -0
- data/lib/google/pubsub/v1/pubsub_services_pb.rb +117 -0
- metadata +233 -0
@@ -0,0 +1,162 @@
|
|
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/pubsub/message"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Pubsub
|
22
|
+
##
|
23
|
+
# # ReceivedMessage
|
24
|
+
#
|
25
|
+
# Represents a Pub/Sub {Message} that can be acknowledged or delayed.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# require "google/cloud"
|
29
|
+
#
|
30
|
+
# gcloud = Google::Cloud.new
|
31
|
+
# pubsub = gcloud.pubsub
|
32
|
+
#
|
33
|
+
# sub = pubsub.subscription "my-topic-sub"
|
34
|
+
# received_message = sub.pull.first
|
35
|
+
# if received_message
|
36
|
+
# puts received_message.message.data
|
37
|
+
# received_message.acknowledge!
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
class ReceivedMessage
|
41
|
+
##
|
42
|
+
# @private The {Subscription} object.
|
43
|
+
attr_accessor :subscription
|
44
|
+
|
45
|
+
##
|
46
|
+
# @private The gRPC Google::Pubsub::V1::ReceivedMessage object.
|
47
|
+
attr_accessor :grpc
|
48
|
+
|
49
|
+
##
|
50
|
+
# @private Create an empty {Subscription} object.
|
51
|
+
def initialize
|
52
|
+
@subscription = nil
|
53
|
+
@grpc = Google::Pubsub::V1::ReceivedMessage.new
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# The acknowledgment ID for the message.
|
58
|
+
def ack_id
|
59
|
+
@grpc.ack_id
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The received message.
|
64
|
+
def message
|
65
|
+
Message.from_grpc @grpc.message
|
66
|
+
end
|
67
|
+
alias_method :msg, :message
|
68
|
+
|
69
|
+
##
|
70
|
+
# The received message's data.
|
71
|
+
def data
|
72
|
+
message.data
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# The received message's attributes.
|
77
|
+
def attributes
|
78
|
+
message.attributes
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# The ID of the received message, assigned by the server at publication
|
83
|
+
# time. Guaranteed to be unique within the topic.
|
84
|
+
def message_id
|
85
|
+
message.message_id
|
86
|
+
end
|
87
|
+
alias_method :msg_id, :message_id
|
88
|
+
|
89
|
+
##
|
90
|
+
# Acknowledges receipt of the message.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# require "google/cloud"
|
94
|
+
#
|
95
|
+
# gcloud = Google::Cloud.new
|
96
|
+
# pubsub = gcloud.pubsub
|
97
|
+
#
|
98
|
+
# sub = pubsub.subscription "my-topic-sub"
|
99
|
+
# received_message = sub.pull.first
|
100
|
+
# if received_message
|
101
|
+
# puts received_message.message.data
|
102
|
+
# received_message.acknowledge!
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
def acknowledge!
|
106
|
+
ensure_subscription!
|
107
|
+
subscription.acknowledge ack_id
|
108
|
+
end
|
109
|
+
alias_method :ack!, :acknowledge!
|
110
|
+
|
111
|
+
##
|
112
|
+
# Modifies the acknowledge deadline for the message.
|
113
|
+
#
|
114
|
+
# This indicates that more time is needed to process the message, or to
|
115
|
+
# make the message available for redelivery.
|
116
|
+
#
|
117
|
+
# @param [Integer] new_deadline The new ack deadline in seconds from the
|
118
|
+
# time this request is sent to the Pub/Sub system. Must be >= 0. For
|
119
|
+
# example, if the value is `10`, the new ack deadline will expire 10
|
120
|
+
# seconds after the call is made. Specifying `0` may immediately make
|
121
|
+
# the message available for another pull request.
|
122
|
+
#
|
123
|
+
# @example
|
124
|
+
# require "google/cloud"
|
125
|
+
#
|
126
|
+
# gcloud = Google::Cloud.new
|
127
|
+
# pubsub = gcloud.pubsub
|
128
|
+
#
|
129
|
+
# sub = pubsub.subscription "my-topic-sub"
|
130
|
+
# received_message = sub.pull.first
|
131
|
+
# if received_message
|
132
|
+
# puts received_message.message.data
|
133
|
+
# # Delay for 2 minutes
|
134
|
+
# received_message.delay! 120
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
def delay! new_deadline
|
138
|
+
ensure_subscription!
|
139
|
+
subscription.delay new_deadline, ack_id
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# @private New ReceivedMessage from a
|
144
|
+
# Google::Pubsub::V1::ReceivedMessage object.
|
145
|
+
def self.from_grpc grpc, subscription
|
146
|
+
new.tap do |rm|
|
147
|
+
rm.grpc = grpc
|
148
|
+
rm.subscription = subscription
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
protected
|
153
|
+
|
154
|
+
##
|
155
|
+
# Raise an error unless an active subscription is available.
|
156
|
+
def ensure_subscription!
|
157
|
+
fail "Must have active subscription" unless subscription
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,340 @@
|
|
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
|
+
require "google/cloud/core/grpc_backoff"
|
18
|
+
require "google/pubsub/v1/pubsub_services_pb"
|
19
|
+
require "google/iam/v1/iam_policy_services"
|
20
|
+
require "google/cloud/core/grpc_utils"
|
21
|
+
require "json"
|
22
|
+
|
23
|
+
module Google
|
24
|
+
module Cloud
|
25
|
+
module Pubsub
|
26
|
+
##
|
27
|
+
# @private Represents the gRPC Pub/Sub service, including all the API
|
28
|
+
# methods.
|
29
|
+
class Service
|
30
|
+
attr_accessor :project, :credentials, :host, :retries, :timeout
|
31
|
+
|
32
|
+
##
|
33
|
+
# Creates a new Service instance.
|
34
|
+
def initialize project, credentials, host: nil, retries: nil,
|
35
|
+
timeout: nil
|
36
|
+
@project = project
|
37
|
+
@credentials = credentials
|
38
|
+
@host = host || "pubsub.googleapis.com"
|
39
|
+
@retries = retries
|
40
|
+
@timeout = timeout
|
41
|
+
end
|
42
|
+
|
43
|
+
def creds
|
44
|
+
return credentials if insecure?
|
45
|
+
GRPC::Core::ChannelCredentials.new.compose \
|
46
|
+
GRPC::Core::CallCredentials.new credentials.client.updater_proc
|
47
|
+
end
|
48
|
+
|
49
|
+
def subscriber
|
50
|
+
return mocked_subscriber if mocked_subscriber
|
51
|
+
@subscriber ||= Google::Pubsub::V1::Subscriber::Stub.new(
|
52
|
+
host, creds, timeout: timeout)
|
53
|
+
end
|
54
|
+
attr_accessor :mocked_subscriber
|
55
|
+
|
56
|
+
def publisher
|
57
|
+
return mocked_publisher if mocked_publisher
|
58
|
+
@publisher ||= Google::Pubsub::V1::Publisher::Stub.new(
|
59
|
+
host, creds, timeout: timeout)
|
60
|
+
end
|
61
|
+
attr_accessor :mocked_publisher
|
62
|
+
|
63
|
+
def iam
|
64
|
+
return mocked_iam if mocked_iam
|
65
|
+
@iam ||= Google::Iam::V1::IAMPolicy::Stub.new(
|
66
|
+
host, creds, timeout: timeout)
|
67
|
+
end
|
68
|
+
attr_accessor :mocked_iam
|
69
|
+
|
70
|
+
def insecure?
|
71
|
+
credentials == :this_channel_is_insecure
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Gets the configuration of a topic.
|
76
|
+
# Since the topic only has the name attribute,
|
77
|
+
# this method is only useful to check the existence of a topic.
|
78
|
+
# If other attributes are added in the future,
|
79
|
+
# they will be returned here.
|
80
|
+
def get_topic topic_name, options = {}
|
81
|
+
topic_req = Google::Pubsub::V1::GetTopicRequest.new.tap do |r|
|
82
|
+
r.topic = topic_path(topic_name, options)
|
83
|
+
end
|
84
|
+
|
85
|
+
execute { publisher.get_topic topic_req }
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Lists matching topics.
|
90
|
+
def list_topics options = {}
|
91
|
+
topics_req = Google::Pubsub::V1::ListTopicsRequest.new.tap do |r|
|
92
|
+
r.project = project_path(options)
|
93
|
+
r.page_token = options[:token] if options[:token]
|
94
|
+
r.page_size = options[:max] if options[:max]
|
95
|
+
end
|
96
|
+
|
97
|
+
execute { publisher.list_topics topics_req }
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Creates the given topic with the given name.
|
102
|
+
def create_topic topic_name, options = {}
|
103
|
+
topic_req = Google::Pubsub::V1::Topic.new.tap do |r|
|
104
|
+
r.name = topic_path(topic_name, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
execute { publisher.create_topic topic_req }
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Deletes the topic with the given name. All subscriptions to this topic
|
112
|
+
# are also deleted. Raises GRPC status code 5 if the topic does not
|
113
|
+
# exist. After a topic is deleted, a new topic may be created with the
|
114
|
+
# same name.
|
115
|
+
def delete_topic topic_name
|
116
|
+
topic_req = Google::Pubsub::V1::DeleteTopicRequest.new.tap do |r|
|
117
|
+
r.topic = topic_path(topic_name)
|
118
|
+
end
|
119
|
+
|
120
|
+
execute { publisher.delete_topic topic_req }
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Adds one or more messages to the topic.
|
125
|
+
# Raises GRPC status code 5 if the topic does not exist.
|
126
|
+
# The messages parameter is an array of arrays.
|
127
|
+
# The first element is the data, second is attributes hash.
|
128
|
+
def publish topic, messages
|
129
|
+
publish_req = Google::Pubsub::V1::PublishRequest.new(
|
130
|
+
topic: topic_path(topic),
|
131
|
+
messages: messages.map do |data, attributes|
|
132
|
+
Google::Pubsub::V1::PubsubMessage.new(
|
133
|
+
data: data, attributes: attributes)
|
134
|
+
end
|
135
|
+
)
|
136
|
+
|
137
|
+
execute { publisher.publish publish_req }
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Gets the details of a subscription.
|
142
|
+
def get_subscription subscription_name, options = {}
|
143
|
+
sub_req = Google::Pubsub::V1::GetSubscriptionRequest.new(
|
144
|
+
subscription: subscription_path(subscription_name, options)
|
145
|
+
)
|
146
|
+
|
147
|
+
execute { subscriber.get_subscription sub_req }
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Lists matching subscriptions by project and topic.
|
152
|
+
def list_topics_subscriptions topic, options = {}
|
153
|
+
list_params = { topic: topic_path(topic, options),
|
154
|
+
page_token: options[:token],
|
155
|
+
page_size: options[:max]
|
156
|
+
}.delete_if { |_, v| v.nil? }
|
157
|
+
list_req = Google::Pubsub::V1::ListTopicSubscriptionsRequest.new \
|
158
|
+
list_params
|
159
|
+
|
160
|
+
execute { publisher.list_topic_subscriptions list_req }
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Lists matching subscriptions by project.
|
165
|
+
def list_subscriptions options = {}
|
166
|
+
list_params = { project: project_path(options),
|
167
|
+
page_token: options[:token],
|
168
|
+
page_size: options[:max]
|
169
|
+
}.delete_if { |_, v| v.nil? }
|
170
|
+
list_req = Google::Pubsub::V1::ListSubscriptionsRequest.new(
|
171
|
+
list_params)
|
172
|
+
|
173
|
+
execute { subscriber.list_subscriptions list_req }
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Creates a subscription on a given topic for a given subscriber.
|
178
|
+
def create_subscription topic, subscription_name, options = {}
|
179
|
+
sub_params = { name: subscription_path(subscription_name, options),
|
180
|
+
topic: topic_path(topic),
|
181
|
+
ack_deadline_seconds: options[:deadline]
|
182
|
+
}.delete_if { |_, v| v.nil? }
|
183
|
+
sub_req = Google::Pubsub::V1::Subscription.new sub_params
|
184
|
+
if options[:endpoint]
|
185
|
+
sub_req.push_config = Google::Pubsub::V1::PushConfig.new(
|
186
|
+
push_endpoint: options[:endpoint],
|
187
|
+
attributes: (options[:attributes] || {}).to_h)
|
188
|
+
end
|
189
|
+
|
190
|
+
execute { subscriber.create_subscription sub_req }
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Deletes an existing subscription.
|
195
|
+
# All pending messages in the subscription are immediately dropped.
|
196
|
+
def delete_subscription subscription
|
197
|
+
del_req = Google::Pubsub::V1::DeleteSubscriptionRequest.new(
|
198
|
+
subscription: subscription_path(subscription)
|
199
|
+
)
|
200
|
+
|
201
|
+
execute { subscriber.delete_subscription del_req }
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Pulls a single message from the server.
|
206
|
+
def pull subscription, options = {}
|
207
|
+
pull_req = Google::Pubsub::V1::PullRequest.new(
|
208
|
+
subscription: subscription_path(subscription, options),
|
209
|
+
return_immediately: !(!options.fetch(:immediate, true)),
|
210
|
+
max_messages: options.fetch(:max, 100).to_i
|
211
|
+
)
|
212
|
+
|
213
|
+
execute { subscriber.pull pull_req }
|
214
|
+
end
|
215
|
+
|
216
|
+
##
|
217
|
+
# Acknowledges receipt of a message.
|
218
|
+
def acknowledge subscription, *ack_ids
|
219
|
+
ack_req = Google::Pubsub::V1::AcknowledgeRequest.new(
|
220
|
+
subscription: subscription_path(subscription),
|
221
|
+
ack_ids: ack_ids
|
222
|
+
)
|
223
|
+
|
224
|
+
execute { subscriber.acknowledge ack_req }
|
225
|
+
end
|
226
|
+
|
227
|
+
##
|
228
|
+
# Modifies the PushConfig for a specified subscription.
|
229
|
+
def modify_push_config subscription, endpoint, attributes
|
230
|
+
# Convert attributes to strings to match the protobuf definition
|
231
|
+
attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
|
232
|
+
|
233
|
+
mpc_req = Google::Pubsub::V1::ModifyPushConfigRequest.new(
|
234
|
+
subscription: subscription_path(subscription),
|
235
|
+
push_config: Google::Pubsub::V1::PushConfig.new(
|
236
|
+
push_endpoint: endpoint,
|
237
|
+
attributes: attributes
|
238
|
+
)
|
239
|
+
)
|
240
|
+
|
241
|
+
execute { subscriber.modify_push_config mpc_req }
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Modifies the ack deadline for a specific message.
|
246
|
+
def modify_ack_deadline subscription, ids, deadline
|
247
|
+
mad_req = Google::Pubsub::V1::ModifyAckDeadlineRequest.new(
|
248
|
+
subscription: subscription_path(subscription),
|
249
|
+
ack_ids: Array(ids),
|
250
|
+
ack_deadline_seconds: deadline
|
251
|
+
)
|
252
|
+
|
253
|
+
execute { subscriber.modify_ack_deadline mad_req }
|
254
|
+
end
|
255
|
+
|
256
|
+
def get_topic_policy topic_name, options = {}
|
257
|
+
get_req = Google::Iam::V1::GetIamPolicyRequest.new(
|
258
|
+
resource: topic_path(topic_name, options)
|
259
|
+
)
|
260
|
+
|
261
|
+
execute { iam.get_iam_policy get_req }
|
262
|
+
end
|
263
|
+
|
264
|
+
def set_topic_policy topic_name, new_policy, options = {}
|
265
|
+
set_req = Google::Iam::V1::SetIamPolicyRequest.new(
|
266
|
+
resource: topic_path(topic_name, options),
|
267
|
+
policy: new_policy
|
268
|
+
)
|
269
|
+
|
270
|
+
execute { iam.set_iam_policy set_req }
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_topic_permissions topic_name, permissions, options = {}
|
274
|
+
test_req = Google::Iam::V1::TestIamPermissionsRequest.new(
|
275
|
+
resource: topic_path(topic_name, options),
|
276
|
+
permissions: permissions
|
277
|
+
)
|
278
|
+
|
279
|
+
execute { iam.test_iam_permissions test_req }
|
280
|
+
end
|
281
|
+
|
282
|
+
def get_subscription_policy subscription_name, options = {}
|
283
|
+
get_req = Google::Iam::V1::GetIamPolicyRequest.new(
|
284
|
+
resource: subscription_path(subscription_name, options)
|
285
|
+
)
|
286
|
+
|
287
|
+
execute { iam.get_iam_policy get_req }
|
288
|
+
end
|
289
|
+
|
290
|
+
def set_subscription_policy subscription_name, new_policy, options = {}
|
291
|
+
set_req = Google::Iam::V1::SetIamPolicyRequest.new(
|
292
|
+
resource: subscription_path(subscription_name, options),
|
293
|
+
policy: new_policy
|
294
|
+
)
|
295
|
+
|
296
|
+
execute { iam.set_iam_policy set_req }
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_subscription_permissions subscription_name,
|
300
|
+
permissions, options = {}
|
301
|
+
test_req = Google::Iam::V1::TestIamPermissionsRequest.new(
|
302
|
+
resource: subscription_path(subscription_name, options),
|
303
|
+
permissions: permissions
|
304
|
+
)
|
305
|
+
|
306
|
+
execute { iam.test_iam_permissions test_req }
|
307
|
+
end
|
308
|
+
|
309
|
+
def project_path options = {}
|
310
|
+
project_name = options[:project] || project
|
311
|
+
"projects/#{project_name}"
|
312
|
+
end
|
313
|
+
|
314
|
+
def topic_path topic_name, options = {}
|
315
|
+
return topic_name if topic_name.to_s.include? "/"
|
316
|
+
"#{project_path(options)}/topics/#{topic_name}"
|
317
|
+
end
|
318
|
+
|
319
|
+
def subscription_path subscription_name, options = {}
|
320
|
+
return subscription_name if subscription_name.to_s.include? "/"
|
321
|
+
"#{project_path(options)}/subscriptions/#{subscription_name}"
|
322
|
+
end
|
323
|
+
|
324
|
+
def inspect
|
325
|
+
"#{self.class}(#{@project})"
|
326
|
+
end
|
327
|
+
|
328
|
+
protected
|
329
|
+
|
330
|
+
def execute
|
331
|
+
Google::Cloud::Core::GrpcBackoff.new(retries: retries).execute do
|
332
|
+
yield
|
333
|
+
end
|
334
|
+
rescue GRPC::BadStatus => e
|
335
|
+
raise Error.from_error(e)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|