google-cloud-pubsub 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +18 -0
  3. data/AUTHENTICATION.md +177 -0
  4. data/CHANGELOG.md +538 -0
  5. data/CODE_OF_CONDUCT.md +40 -0
  6. data/CONTRIBUTING.md +188 -0
  7. data/EMULATOR.md +37 -0
  8. data/LICENSE +201 -0
  9. data/LOGGING.md +32 -0
  10. data/OVERVIEW.md +557 -0
  11. data/TROUBLESHOOTING.md +31 -0
  12. data/lib/google-cloud-pubsub.rb +139 -0
  13. data/lib/google/cloud/pubsub.rb +173 -0
  14. data/lib/google/cloud/pubsub/async_publisher.rb +399 -0
  15. data/lib/google/cloud/pubsub/async_publisher/batch.rb +309 -0
  16. data/lib/google/cloud/pubsub/batch_publisher.rb +99 -0
  17. data/lib/google/cloud/pubsub/convert.rb +91 -0
  18. data/lib/google/cloud/pubsub/credentials.rb +47 -0
  19. data/lib/google/cloud/pubsub/errors.rb +85 -0
  20. data/lib/google/cloud/pubsub/message.rb +158 -0
  21. data/lib/google/cloud/pubsub/policy.rb +187 -0
  22. data/lib/google/cloud/pubsub/project.rb +393 -0
  23. data/lib/google/cloud/pubsub/publish_result.rb +103 -0
  24. data/lib/google/cloud/pubsub/received_message.rb +297 -0
  25. data/lib/google/cloud/pubsub/retry_policy.rb +90 -0
  26. data/lib/google/cloud/pubsub/service.rb +514 -0
  27. data/lib/google/cloud/pubsub/snapshot.rb +202 -0
  28. data/lib/google/cloud/pubsub/snapshot/list.rb +178 -0
  29. data/lib/google/cloud/pubsub/subscriber.rb +399 -0
  30. data/lib/google/cloud/pubsub/subscriber/enumerator_queue.rb +54 -0
  31. data/lib/google/cloud/pubsub/subscriber/inventory.rb +166 -0
  32. data/lib/google/cloud/pubsub/subscriber/sequencer.rb +115 -0
  33. data/lib/google/cloud/pubsub/subscriber/stream.rb +401 -0
  34. data/lib/google/cloud/pubsub/subscriber/timed_unary_buffer.rb +231 -0
  35. data/lib/google/cloud/pubsub/subscription.rb +1279 -0
  36. data/lib/google/cloud/pubsub/subscription/list.rb +205 -0
  37. data/lib/google/cloud/pubsub/subscription/push_config.rb +244 -0
  38. data/lib/google/cloud/pubsub/topic.rb +934 -0
  39. data/lib/google/cloud/pubsub/topic/list.rb +171 -0
  40. data/lib/google/cloud/pubsub/v1.rb +17 -0
  41. data/lib/google/cloud/pubsub/v1/credentials.rb +41 -0
  42. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/iam_policy.rb +21 -0
  43. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/options.rb +21 -0
  44. data/lib/google/cloud/pubsub/v1/doc/google/iam/v1/policy.rb +21 -0
  45. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/duration.rb +91 -0
  46. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/empty.rb +29 -0
  47. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/field_mask.rb +222 -0
  48. data/lib/google/cloud/pubsub/v1/doc/google/protobuf/timestamp.rb +113 -0
  49. data/lib/google/cloud/pubsub/v1/doc/google/pubsub/v1/pubsub.rb +833 -0
  50. data/lib/google/cloud/pubsub/v1/doc/google/type/expr.rb +19 -0
  51. data/lib/google/cloud/pubsub/v1/publisher_client.rb +928 -0
  52. data/lib/google/cloud/pubsub/v1/publisher_client_config.json +120 -0
  53. data/lib/google/cloud/pubsub/v1/subscriber_client.rb +1466 -0
  54. data/lib/google/cloud/pubsub/v1/subscriber_client_config.json +153 -0
  55. data/lib/google/cloud/pubsub/version.rb +24 -0
  56. data/lib/google/pubsub/v1/pubsub_pb.rb +269 -0
  57. data/lib/google/pubsub/v1/pubsub_services_pb.rb +215 -0
  58. metadata +337 -0
@@ -0,0 +1,309 @@
1
+ # Copyright 2019 Google LLC
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
+ # https://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 "monitor"
17
+ require "google/cloud/pubsub/errors"
18
+
19
+ module Google
20
+ module Cloud
21
+ module PubSub
22
+ class AsyncPublisher
23
+ ##
24
+ # @private
25
+ class Batch
26
+ include MonitorMixin
27
+
28
+ attr_reader :items, :ordering_key
29
+
30
+ def initialize publisher, ordering_key
31
+ # init MonitorMixin
32
+ super()
33
+
34
+ @publisher = publisher
35
+ @ordering_key = ordering_key
36
+ @items = []
37
+ @queue = []
38
+ @default_message_bytes = publisher.topic_name.bytesize + 2
39
+ @total_message_bytes = @default_message_bytes
40
+ @publishing = false
41
+ @stopping = false
42
+ @canceled = false
43
+ end
44
+
45
+ ##
46
+ # Adds a message and callback to the batch.
47
+ #
48
+ # The method will indicate how the message is added. It will either be
49
+ # added to the active list of items, it will be queued to be picked up
50
+ # once the active publishing job has been completed, or it will
51
+ # indicate that the batch is full and a publishing job should be
52
+ # created.
53
+ #
54
+ # @param [Google::Cloud::PubSub::V1::PubsubMessage] msg The message.
55
+ # @param [Proc, nil] callback The callback.
56
+ #
57
+ # @return [Symbol] The state of the batch.
58
+ #
59
+ # * `:added` - Added to the active list of items to be published.
60
+ # * `:queued` - Batch is publishing, and the messsage is queued.
61
+ # * `:full` - Batch is full and ready to be published, and the
62
+ # message is queued.
63
+ #
64
+ def add msg, callback
65
+ synchronize do
66
+ raise AsyncPublisherStopped if @stopping
67
+ raise OrderingKeyError, @ordering_key if @canceled
68
+
69
+ if @publishing
70
+ queue_add msg, callback
71
+ :queued
72
+ elsif try_add msg, callback
73
+ :added
74
+ else
75
+ queue_add msg, callback
76
+ :full
77
+ end
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Marks the batch to be published.
83
+ #
84
+ # The method will indicate whether a new publishing job should be
85
+ # started to publish the batch. See {publishing?}.
86
+ #
87
+ # @param [Boolean] stop Indicates whether the batch should also be
88
+ # marked for stopping, and any existing publish job should publish
89
+ # all items until the batch is empty.
90
+ #
91
+ # @return [Boolean] Returns whether a new publishing job should be
92
+ # started to publish the batch. If the batch is already being
93
+ # published then this will return `false`.
94
+ #
95
+ def publish! stop: nil
96
+ synchronize do
97
+ @stopping = true if stop
98
+
99
+ return false if @canceled
100
+
101
+ # If we are already publishing, do not indicate a new job needs to
102
+ # be started.
103
+ return false if @publishing
104
+
105
+ @publishing = !(@items.empty? && @queue.empty?)
106
+ end
107
+ end
108
+
109
+ ##
110
+ # Indicates whether the batch has an active publishing job.
111
+ #
112
+ # @return [Boolean]
113
+ #
114
+ def publishing?
115
+ # This probably does not need to be synchronized
116
+ @publishing
117
+ end
118
+
119
+ ##
120
+ # Indicates whether the batch has been stopped and all items will be
121
+ # published until the batch is empty.
122
+ #
123
+ # @return [Boolean]
124
+ #
125
+ def stopping?
126
+ # This does not need to be synchronized because nothing un-stops
127
+ @stopping
128
+ end
129
+
130
+ ##
131
+ # Rebalances the batch by moving any queued items that will fit into
132
+ # the active item list.
133
+ #
134
+ # This method is only intended to be used by the active publishing
135
+ # job.
136
+ #
137
+ def rebalance!
138
+ synchronize do
139
+ return [] if @canceled
140
+
141
+ until @queue.empty?
142
+ item = @queue.first
143
+ if try_add item.msg, item.callback
144
+ @queue.shift
145
+ next
146
+ end
147
+ break
148
+ end
149
+
150
+ @items
151
+ end
152
+ end
153
+
154
+ # rubocop:disable Metrics/MethodLength
155
+
156
+ ##
157
+ # Resets the batch after a successful publish. This clears the active
158
+ # item list and moves the queued items that will fit into the active
159
+ # item list.
160
+ #
161
+ # If the batch has enough queued items to fill the batch again, the
162
+ # publishing job should continue to publish the reset batch until the
163
+ # batch indicated it should stop.
164
+ #
165
+ # This method is only intended to be used by the active publishing
166
+ # job.
167
+ #
168
+ # @return [Boolean] Whether the active publishing job should continue
169
+ # publishing after the reset.
170
+ #
171
+ def reset!
172
+ synchronize do
173
+ @items = []
174
+ @total_message_bytes = @default_message_bytes
175
+
176
+ if @canceled
177
+ @queue = []
178
+ @publishing = false
179
+ return false
180
+ end
181
+
182
+ until @queue.empty?
183
+ item = @queue.first
184
+ added = try_add item.msg, item.callback
185
+ break unless added
186
+ @queue.shift
187
+ end
188
+
189
+ return false unless @publishing
190
+ if @items.empty?
191
+ @publishing = false
192
+ return false
193
+ else
194
+ return true if stopping?
195
+ if @queue.empty?
196
+ @publishing = false
197
+ return false
198
+ end
199
+ end
200
+ end
201
+ true
202
+ end
203
+
204
+ # rubocop:enable Metrics/MethodLength
205
+
206
+ ##
207
+ # Cancel the batch and hault futher batches until resumed. See
208
+ # {#resume!} and {#canceled?}.
209
+ #
210
+ # @return [Array<Item}] All items, including queued items
211
+ #
212
+ def cancel!
213
+ synchronize do
214
+ @canceled = true
215
+ @items + @queue
216
+ end
217
+ end
218
+
219
+ ##
220
+ # Resume the batch and proceed to publish messages. See {#cancel!} and
221
+ # {#canceled?}.
222
+ #
223
+ # @return [Boolean] Whether the batch was resumed.
224
+ #
225
+ def resume!
226
+ synchronize do
227
+ # Return false if the batch is not canceled
228
+ return false unless @canceled
229
+
230
+ @items = []
231
+ @queue = []
232
+ @total_message_bytes = @default_message_bytes
233
+ @publishing = false
234
+ @canceled = false
235
+ end
236
+ true
237
+ end
238
+
239
+ ##
240
+ # Indicates whether the batch has been canceled due to an error while
241
+ # publishing. See {#cancel!} and {#resume!}.
242
+ #
243
+ # @return [Boolean]
244
+ #
245
+ def canceled?
246
+ # This does not need to be synchronized because nothing un-stops
247
+ synchronize { @canceled }
248
+ end
249
+
250
+ ##
251
+ # Determines whether the batch is empty and ready to be culled.
252
+ #
253
+ def empty?
254
+ synchronize do
255
+ return false if @publishing || @canceled || @stopping
256
+
257
+ @items.empty? && @queue.empty?
258
+ end
259
+ end
260
+
261
+ protected
262
+
263
+ def items_add msg, callback
264
+ item = Item.new msg, callback
265
+ @items << item
266
+ @total_message_bytes += item.bytesize + 2
267
+ end
268
+
269
+ def try_add msg, callback
270
+ if @items.empty?
271
+ # Always add when empty, even if bytesize is bigger than total
272
+ items_add msg, callback
273
+ return true
274
+ end
275
+ new_message_count = total_message_count + 1
276
+ new_message_bytes = total_message_bytes + msg.to_proto.bytesize + 2
277
+ if new_message_count > @publisher.max_messages ||
278
+ new_message_bytes >= @publisher.max_bytes
279
+ return false
280
+ end
281
+ items_add msg, callback
282
+ true
283
+ end
284
+
285
+ def queue_add msg, callback
286
+ item = Item.new msg, callback
287
+ @queue << item
288
+ end
289
+
290
+ def total_message_count
291
+ @items.count
292
+ end
293
+
294
+ def total_message_bytes
295
+ @total_message_bytes
296
+ end
297
+
298
+ Item = Struct.new :msg, :callback do
299
+ def bytesize
300
+ msg.to_proto.bytesize
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+ Pubsub = PubSub unless const_defined? :Pubsub
308
+ end
309
+ end
@@ -0,0 +1,99 @@
1
+ # Copyright 2015 Google LLC
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
+ # https://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
+ module Google
17
+ module Cloud
18
+ module PubSub
19
+ ##
20
+ # Topic Batch Publisher object used to publish multiple messages at
21
+ # once.
22
+ #
23
+ # @example
24
+ # require "google/cloud/pubsub"
25
+ #
26
+ # pubsub = Google::Cloud::PubSub.new
27
+ #
28
+ # topic = pubsub.topic "my-topic"
29
+ # msgs = topic.publish do |t|
30
+ # t.publish "task 1 completed", foo: :bar
31
+ # t.publish "task 2 completed", foo: :baz
32
+ # t.publish "task 3 completed", foo: :bif
33
+ # end
34
+ class BatchPublisher
35
+ ##
36
+ # @private The messages to publish
37
+ attr_reader :messages
38
+
39
+ ##
40
+ # @private Create a new instance of the object.
41
+ def initialize data = nil, attributes = {}
42
+ @messages = []
43
+ @mode = :batch
44
+ return if data.nil?
45
+ @mode = :single
46
+ publish data, attributes
47
+ end
48
+
49
+ ##
50
+ # Add a message to the batch to be published to the topic.
51
+ # All messages added to the batch will be published at once.
52
+ # See {Google::Cloud::PubSub::Topic#publish}
53
+ def publish data, attributes = {}
54
+ @messages << create_pubsub_message(data, attributes)
55
+ end
56
+
57
+ ##
58
+ # @private Create Message objects with message ids.
59
+ def to_gcloud_messages message_ids
60
+ msgs = @messages.zip(Array(message_ids)).map do |msg, id|
61
+ msg.message_id = id
62
+ Message.from_grpc msg
63
+ end
64
+ # Return just one Message if a single publish,
65
+ # otherwise return the array of Messages.
66
+ if @mode == :single && msgs.count <= 1
67
+ msgs.first
68
+ else
69
+ msgs
70
+ end
71
+ end
72
+
73
+ protected
74
+
75
+ def create_pubsub_message data, attributes
76
+ attributes ||= {}
77
+ if data.is_a?(::Hash) && attributes.empty?
78
+ attributes = data
79
+ data = nil
80
+ end
81
+ # Convert IO-ish objects to strings
82
+ if data.respond_to?(:read) && data.respond_to?(:rewind)
83
+ data.rewind
84
+ data = data.read
85
+ end
86
+ # Convert data to encoded byte array to match the protobuf defn
87
+ data_bytes = String(data).dup.force_encoding(Encoding::ASCII_8BIT).freeze
88
+
89
+ # Convert attributes to strings to match the protobuf definition
90
+ attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
91
+
92
+ Google::Cloud::PubSub::V1::PubsubMessage.new data: data_bytes, attributes: attributes
93
+ end
94
+ end
95
+ end
96
+
97
+ Pubsub = PubSub unless const_defined? :Pubsub
98
+ end
99
+ end
@@ -0,0 +1,91 @@
1
+ # Copyright 2017 Google LLC
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
+ # https://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 "time"
17
+
18
+ module Google
19
+ module Cloud
20
+ module PubSub
21
+ ##
22
+ # @private Helper module for converting Pub/Sub values.
23
+ module Convert
24
+ module ClassMethods
25
+ def time_to_timestamp time
26
+ return nil if time.nil?
27
+
28
+ # Force the object to be a Time object.
29
+ time = time.to_time
30
+
31
+ Google::Protobuf::Timestamp.new seconds: time.to_i, nanos: time.nsec
32
+ end
33
+
34
+ def timestamp_to_time timestamp
35
+ return nil if timestamp.nil?
36
+
37
+ Time.at timestamp.seconds, Rational(timestamp.nanos, 1000)
38
+ end
39
+
40
+ def number_to_duration number
41
+ return nil if number.nil?
42
+
43
+ Google::Protobuf::Duration.new seconds: number.to_i, nanos: (number.remainder(1) * 1_000_000_000).round
44
+ end
45
+
46
+ def duration_to_number duration
47
+ return nil if duration.nil?
48
+
49
+ return duration.seconds if duration.nanos.zero?
50
+
51
+ duration.seconds + (duration.nanos / 1_000_000_000.0)
52
+ end
53
+
54
+ def pubsub_message data, attributes, ordering_key, extra_attrs
55
+ # TODO: allow data to be a Message object,
56
+ # then ensure attributes and ordering_key are nil
57
+ if data.is_a?(::Hash) && (attributes.nil? || attributes.empty?)
58
+ attributes = data.merge extra_attrs
59
+ data = nil
60
+ else
61
+ attributes = Hash(attributes).merge extra_attrs
62
+ end
63
+ # Convert IO-ish objects to strings
64
+ if data.respond_to?(:read) && data.respond_to?(:rewind)
65
+ data.rewind
66
+ data = data.read
67
+ end
68
+ # Convert data to encoded byte array to match the protobuf defn
69
+ data_bytes = String(data).dup.force_encoding(Encoding::ASCII_8BIT).freeze
70
+
71
+ # Convert attributes to strings to match the protobuf definition
72
+ attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
73
+
74
+ # Ordering Key must always be a string
75
+ ordering_key = String(ordering_key).freeze
76
+
77
+ Google::Cloud::PubSub::V1::PubsubMessage.new(
78
+ data: data_bytes,
79
+ attributes: attributes,
80
+ ordering_key: ordering_key
81
+ )
82
+ end
83
+ end
84
+
85
+ extend ClassMethods
86
+ end
87
+ end
88
+
89
+ Pubsub = PubSub unless const_defined? :Pubsub
90
+ end
91
+ end