google-cloud-pubsub 0.20.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 +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
|