google-cloud-pubsub 0.20.0 → 2.6.1

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.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +18 -0
  3. data/AUTHENTICATION.md +178 -0
  4. data/CHANGELOG.md +659 -0
  5. data/CODE_OF_CONDUCT.md +40 -0
  6. data/CONTRIBUTING.md +187 -0
  7. data/EMULATOR.md +37 -0
  8. data/LICENSE +201 -0
  9. data/LOGGING.md +32 -0
  10. data/OVERVIEW.md +528 -0
  11. data/TROUBLESHOOTING.md +31 -0
  12. data/lib/google/cloud/pubsub/async_publisher/batch.rb +310 -0
  13. data/lib/google/cloud/pubsub/async_publisher.rb +402 -0
  14. data/lib/google/cloud/pubsub/batch_publisher.rb +100 -0
  15. data/lib/google/cloud/pubsub/convert.rb +91 -0
  16. data/lib/google/cloud/pubsub/credentials.rb +26 -10
  17. data/lib/google/cloud/pubsub/errors.rb +85 -0
  18. data/lib/google/cloud/pubsub/message.rb +82 -20
  19. data/lib/google/cloud/pubsub/policy.rb +40 -61
  20. data/lib/google/cloud/pubsub/project.rb +405 -265
  21. data/lib/google/cloud/pubsub/publish_result.rb +103 -0
  22. data/lib/google/cloud/pubsub/received_message.rb +165 -30
  23. data/lib/google/cloud/pubsub/retry_policy.rb +88 -0
  24. data/lib/google/cloud/pubsub/schema/list.rb +180 -0
  25. data/lib/google/cloud/pubsub/schema.rb +310 -0
  26. data/lib/google/cloud/pubsub/service.rb +304 -162
  27. data/lib/google/cloud/pubsub/snapshot/list.rb +178 -0
  28. data/lib/google/cloud/pubsub/snapshot.rb +205 -0
  29. data/lib/google/cloud/pubsub/subscriber/enumerator_queue.rb +54 -0
  30. data/lib/google/cloud/pubsub/subscriber/inventory.rb +173 -0
  31. data/lib/google/cloud/pubsub/subscriber/sequencer.rb +115 -0
  32. data/lib/google/cloud/pubsub/subscriber/stream.rb +400 -0
  33. data/lib/google/cloud/pubsub/subscriber/timed_unary_buffer.rb +230 -0
  34. data/lib/google/cloud/pubsub/subscriber.rb +417 -0
  35. data/lib/google/cloud/pubsub/subscription/list.rb +38 -43
  36. data/lib/google/cloud/pubsub/subscription/push_config.rb +268 -0
  37. data/lib/google/cloud/pubsub/subscription.rb +1040 -210
  38. data/lib/google/cloud/pubsub/topic/list.rb +32 -37
  39. data/lib/google/cloud/pubsub/topic.rb +726 -177
  40. data/lib/google/cloud/pubsub/version.rb +6 -4
  41. data/lib/google/cloud/pubsub.rb +138 -413
  42. data/lib/google-cloud-pubsub.rb +60 -42
  43. metadata +88 -39
  44. data/lib/google/cloud/pubsub/topic/publisher.rb +0 -87
  45. data/lib/google/iam/v1/iam_policy.rb +0 -33
  46. data/lib/google/iam/v1/iam_policy_services.rb +0 -30
  47. data/lib/google/iam/v1/policy.rb +0 -25
  48. data/lib/google/pubsub/v1/pubsub_pb.rb +0 -129
  49. data/lib/google/pubsub/v1/pubsub_services_pb.rb +0 -117
@@ -0,0 +1,178 @@
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 "delegate"
17
+
18
+ module Google
19
+ module Cloud
20
+ module PubSub
21
+ class Snapshot
22
+ ##
23
+ # Snapshot::List is a special case Array with additional values.
24
+ class List < DelegateClass(::Array)
25
+ ##
26
+ # If not empty, indicates that there are more snapshots
27
+ # that match the request and this value should be passed to
28
+ # the next {Google::Cloud::PubSub::Project#snapshots} to continue.
29
+ attr_accessor :token
30
+
31
+ ##
32
+ # @private Create a new Snapshot::List with an array of values.
33
+ def initialize arr = []
34
+ @prefix = nil
35
+ @token = nil
36
+ @max = nil
37
+ super arr
38
+ end
39
+
40
+ ##
41
+ # Whether there a next page of snapshots.
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ # @example
46
+ # require "google/cloud/pubsub"
47
+ #
48
+ # pubsub = Google::Cloud::PubSub.new
49
+ #
50
+ # snapshots = pubsub.snapshots
51
+ # if snapshots.next?
52
+ # next_snapshots = snapshots.next
53
+ # end
54
+ #
55
+ def next?
56
+ !token.nil?
57
+ end
58
+
59
+ ##
60
+ # Retrieve the next page of snapshots.
61
+ #
62
+ # @return [Snapshot::List]
63
+ #
64
+ # @example
65
+ # require "google/cloud/pubsub"
66
+ #
67
+ # pubsub = Google::Cloud::PubSub.new
68
+ #
69
+ # snapshots = pubsub.snapshots
70
+ # if snapshots.next?
71
+ # next_snapshots = snapshots.next
72
+ # end
73
+ #
74
+ def next
75
+ return nil unless next?
76
+ ensure_service!
77
+ next_snapshots
78
+ end
79
+
80
+ ##
81
+ # Retrieves remaining results by repeatedly invoking {#next} until
82
+ # {#next?} returns `false`. Calls the given block once for each
83
+ # result, which is passed as the argument to the block.
84
+ #
85
+ # An Enumerator is returned if no block is given.
86
+ #
87
+ # This method will make repeated API calls until all remaining results
88
+ # are retrieved. (Unlike `#each`, for example, which merely iterates
89
+ # over the results returned by a single API call.) Use with caution.
90
+ #
91
+ # @param [Integer] request_limit The upper limit of API requests to
92
+ # make to load all snapshots. Default is no limit.
93
+ # @yield [snapshot] The block for accessing each snapshot.
94
+ # @yieldparam [Snapshot] snapshot The snapshot object.
95
+ #
96
+ # @return [Enumerator]
97
+ #
98
+ # @example Iterating each snapshot by passing a block:
99
+ # require "google/cloud/pubsub"
100
+ #
101
+ # pubsub = Google::Cloud::PubSub.new
102
+ #
103
+ # snapshots = pubsub.snapshots
104
+ # snapshots.all do |snapshot|
105
+ # puts snapshot.name
106
+ # end
107
+ #
108
+ # @example Using the enumerator by not passing a block:
109
+ # require "google/cloud/pubsub"
110
+ #
111
+ # pubsub = Google::Cloud::PubSub.new
112
+ #
113
+ # snapshots = pubsub.snapshots
114
+ # all_names = snapshots.all.map do |snapshot|
115
+ # snapshot.name
116
+ # end
117
+ #
118
+ # @example Limit the number of API calls made:
119
+ # require "google/cloud/pubsub"
120
+ #
121
+ # pubsub = Google::Cloud::PubSub.new
122
+ #
123
+ # snapshots = pubsub.snapshots
124
+ # snapshots.all(request_limit: 10) do |snapshot|
125
+ # puts snapshot.name
126
+ # end
127
+ #
128
+ def all request_limit: nil, &block
129
+ request_limit = request_limit.to_i if request_limit
130
+ return enum_for :all, request_limit: request_limit unless block_given?
131
+ results = self
132
+ loop do
133
+ results.each(&block)
134
+ if request_limit
135
+ request_limit -= 1
136
+ break if request_limit.negative?
137
+ end
138
+ break unless results.next?
139
+ results = results.next
140
+ end
141
+ end
142
+
143
+ ##
144
+ # @private New Snapshots::List from a
145
+ # Google::Cloud::PubSub::V1::ListSnapshotsRequest object.
146
+ def self.from_grpc grpc_list, service, max = nil
147
+ subs = new(Array(grpc_list.snapshots).map do |grpc|
148
+ Snapshot.from_grpc grpc, service
149
+ end)
150
+ token = grpc_list.next_page_token
151
+ token = nil if token == "".freeze
152
+ subs.instance_variable_set :@token, token
153
+ subs.instance_variable_set :@service, service
154
+ subs.instance_variable_set :@max, max
155
+ subs
156
+ end
157
+
158
+ protected
159
+
160
+ ##
161
+ # @private Raise an error unless an active connection to the service
162
+ # is available.
163
+ def ensure_service!
164
+ raise "Must have active connection to service" unless @service
165
+ end
166
+
167
+ def next_snapshots
168
+ options = { prefix: @prefix, token: @token, max: @max }
169
+ grpc = @service.list_snapshots options
170
+ self.class.from_grpc grpc, @service, @max
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ Pubsub = PubSub unless const_defined? :Pubsub
177
+ end
178
+ end
@@ -0,0 +1,205 @@
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 "google/cloud/errors"
17
+ require "google/cloud/pubsub/snapshot/list"
18
+ require "google/cloud/pubsub/v1"
19
+
20
+ module Google
21
+ module Cloud
22
+ module PubSub
23
+ ##
24
+ # # Snapshot
25
+ #
26
+ # A named resource created from a subscription to retain a stream of
27
+ # messages from a topic. A snapshot is guaranteed to retain:
28
+ #
29
+ # * The existing backlog on the subscription. More precisely, this is
30
+ # defined as the messages in the subscription's backlog that are
31
+ # unacknowledged upon the successful completion of the
32
+ # `create_snapshot` operation; as well as:
33
+ # * Any messages published to the subscription's topic following the
34
+ # successful completion of the `create_snapshot` operation.
35
+ #
36
+ # @example
37
+ # require "google/cloud/pubsub"
38
+ #
39
+ # pubsub = Google::Cloud::PubSub.new
40
+ # sub = pubsub.subscription "my-sub"
41
+ #
42
+ # snapshot = sub.create_snapshot "my-snapshot"
43
+ # snapshot.name #=> "projects/my-project/snapshots/my-snapshot"
44
+ #
45
+ class Snapshot
46
+ ##
47
+ # @private The Service object.
48
+ attr_accessor :service
49
+
50
+ ##
51
+ # @private The gRPC Google::Cloud::PubSub::V1::Snapshot object.
52
+ attr_accessor :grpc
53
+
54
+ ##
55
+ # @private Create an empty {Snapshot} object.
56
+ def initialize
57
+ @service = nil
58
+ @grpc = Google::Cloud::PubSub::V1::Snapshot.new
59
+ end
60
+
61
+ ##
62
+ # The name of the snapshot.
63
+ #
64
+ # @return [String] A fully-qualified snapshot name in the form
65
+ # `projects/{project_id}/snapshots/{snapshot_id}`.
66
+ def name
67
+ @grpc.name
68
+ end
69
+
70
+ ##
71
+ # The {Topic} from which this snapshot is retaining messages.
72
+ #
73
+ # @return [Topic]
74
+ #
75
+ # @example
76
+ # require "google/cloud/pubsub"
77
+ #
78
+ # pubsub = Google::Cloud::PubSub.new
79
+ # sub = pubsub.subscription "my-sub"
80
+ #
81
+ # snapshot = sub.create_snapshot "my-snapshot"
82
+ # snapshot.topic.name #=> "projects/my-project/topics/my-topic"
83
+ #
84
+ def topic
85
+ Topic.from_name @grpc.topic, service
86
+ end
87
+
88
+ ##
89
+ # The snapshot is guaranteed to exist up until this time.
90
+ # A newly-created snapshot expires no later than 7 days from the time of
91
+ # its creation. Its exact lifetime is determined at creation by the
92
+ # existing backlog in the source subscription. Specifically, the
93
+ # lifetime of the snapshot is 7 days - (age of oldest unacked message in
94
+ # the subscription). For example, consider a subscription whose oldest
95
+ # unacked message is 3 days old. If a snapshot is created from this
96
+ # subscription, the snapshot -- which will always capture this 3-day-old
97
+ # backlog as long as the snapshot exists -- will expire in 4 days.
98
+ #
99
+ # @return [Time] The time until which the snapshot is guaranteed to
100
+ # exist.
101
+ #
102
+ # @example
103
+ # require "google/cloud/pubsub"
104
+ #
105
+ # pubsub = Google::Cloud::PubSub.new
106
+ # sub = pubsub.subscription "my-sub"
107
+ #
108
+ # snapshot = sub.create_snapshot "my-snapshot"
109
+ # snapshot.topic.name #=> "projects/my-project/topics/my-topic"
110
+ # snapshot.expiration_time
111
+ #
112
+ def expiration_time
113
+ self.class.timestamp_from_grpc @grpc.expire_time
114
+ end
115
+
116
+ ##
117
+ # A hash of user-provided labels associated with this snapshot.
118
+ # Labels can be used to organize and group snapshots.See [Creating and
119
+ # Managing Labels](https://cloud.google.com/pubsub/docs/labels).
120
+ #
121
+ # The returned hash is frozen and changes are not allowed. Use
122
+ # {#labels=} to update the labels for this snapshot.
123
+ #
124
+ # @return [Hash] The frozen labels hash.
125
+ #
126
+ def labels
127
+ @grpc.labels.to_h.freeze
128
+ end
129
+
130
+ ##
131
+ # Sets the hash of user-provided labels associated with this
132
+ # snapshot. Labels can be used to organize and group snapshots.
133
+ # Label keys and values can be no longer than 63 characters, can only
134
+ # contain lowercase letters, numeric characters, underscores and dashes.
135
+ # International characters are allowed. Label values are optional. Label
136
+ # keys must start with a letter and each label in the list must have a
137
+ # different key. See [Creating and Managing
138
+ # Labels](https://cloud.google.com/pubsub/docs/labels).
139
+ #
140
+ # @param [Hash] new_labels The new labels hash.
141
+ #
142
+ def labels= new_labels
143
+ raise ArgumentError, "Value must be a Hash" if new_labels.nil?
144
+ labels_map = Google::Protobuf::Map.new :string, :string
145
+ Hash(new_labels).each { |k, v| labels_map[String(k)] = String(v) }
146
+ update_grpc = @grpc.dup
147
+ update_grpc.labels = labels_map
148
+ @grpc = service.update_snapshot update_grpc, :labels
149
+ end
150
+
151
+ ##
152
+ # Removes an existing snapshot. All messages retained in the snapshot
153
+ # are immediately dropped. After a snapshot is deleted, a new one may be
154
+ # created with the same name, but the new one has no association with
155
+ # the old snapshot or its subscription, unless the same subscription is
156
+ # specified.
157
+ #
158
+ # @return [Boolean] Returns `true` if the snapshot was deleted.
159
+ #
160
+ # @example
161
+ # require "google/cloud/pubsub"
162
+ #
163
+ # pubsub = Google::Cloud::PubSub.new
164
+ #
165
+ # pubsub.snapshots.each do |snapshot|
166
+ # snapshot.delete
167
+ # end
168
+ #
169
+ def delete
170
+ ensure_service!
171
+ service.delete_snapshot name
172
+ true
173
+ end
174
+
175
+ ##
176
+ # @private New Snapshot from a Google::Cloud::PubSub::V1::Snapshot
177
+ # object.
178
+ def self.from_grpc grpc, service
179
+ new.tap do |f|
180
+ f.grpc = grpc
181
+ f.service = service
182
+ end
183
+ end
184
+
185
+ ##
186
+ # @private Get a Time object from a Google::Protobuf::Timestamp object.
187
+ def self.timestamp_from_grpc grpc_timestamp
188
+ return nil if grpc_timestamp.nil?
189
+ Time.at grpc_timestamp.seconds, Rational(grpc_timestamp.nanos, 1000)
190
+ end
191
+
192
+ protected
193
+
194
+ ##
195
+ # @private Raise an error unless an active connection to the service is
196
+ # available.
197
+ def ensure_service!
198
+ raise "Must have active connection to service" unless service
199
+ end
200
+ end
201
+ end
202
+
203
+ Pubsub = PubSub unless const_defined? :Pubsub
204
+ end
205
+ end
@@ -0,0 +1,54 @@
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
+ module Google
17
+ module Cloud
18
+ module PubSub
19
+ class Subscriber
20
+ # @private
21
+ class EnumeratorQueue
22
+ def initialize sentinel = nil
23
+ @queue = Queue.new
24
+ @sentinel = sentinel
25
+ end
26
+
27
+ def push obj
28
+ @queue.push obj
29
+ end
30
+
31
+ def quit_and_dump_queue
32
+ objs = []
33
+ objs << @queue.pop until @queue.empty?
34
+ # Signal that the enumerator is ready to end
35
+ @queue.push @sentinel
36
+ objs
37
+ end
38
+
39
+ def each
40
+ return enum_for :each unless block_given?
41
+
42
+ loop do
43
+ obj = @queue.pop
44
+ break if obj.equal? @sentinel
45
+ yield obj
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ Pubsub = PubSub unless const_defined? :Pubsub
53
+ end
54
+ end
@@ -0,0 +1,173 @@
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 "monitor"
17
+
18
+ module Google
19
+ module Cloud
20
+ module PubSub
21
+ class Subscriber
22
+ ##
23
+ # @private
24
+ class Inventory
25
+ InventoryItem = Struct.new :bytesize, :pulled_at do
26
+ def self.from rec_msg
27
+ new rec_msg.to_proto.bytesize, Time.now
28
+ end
29
+ end
30
+
31
+ include MonitorMixin
32
+
33
+ attr_reader :stream
34
+ attr_reader :limit
35
+ attr_reader :bytesize
36
+ attr_reader :extension
37
+ attr_reader :max_duration_per_lease_extension
38
+ attr_reader :use_legacy_flow_control
39
+
40
+ def initialize stream, limit:, bytesize:, extension:, max_duration_per_lease_extension:,
41
+ use_legacy_flow_control:
42
+ super()
43
+ @stream = stream
44
+ @limit = limit
45
+ @bytesize = bytesize
46
+ @extension = extension
47
+ @max_duration_per_lease_extension = max_duration_per_lease_extension
48
+ @use_legacy_flow_control = use_legacy_flow_control
49
+ @inventory = {}
50
+ @wait_cond = new_cond
51
+ end
52
+
53
+ def ack_ids
54
+ @inventory.keys
55
+ end
56
+
57
+ def add *rec_msgs
58
+ rec_msgs.flatten!
59
+ rec_msgs.compact!
60
+ return if rec_msgs.empty?
61
+
62
+ synchronize do
63
+ rec_msgs.each do |rec_msg|
64
+ @inventory[rec_msg.ack_id] = InventoryItem.from rec_msg
65
+ end
66
+ @wait_cond.broadcast
67
+ end
68
+ end
69
+
70
+ def remove *ack_ids
71
+ ack_ids.flatten!
72
+ ack_ids.compact!
73
+ return if ack_ids.empty?
74
+
75
+ synchronize do
76
+ @inventory.delete_if { |ack_id, _| ack_ids.include? ack_id }
77
+ @wait_cond.broadcast
78
+ end
79
+ end
80
+
81
+ def remove_expired!
82
+ synchronize do
83
+ extension_time = Time.new - extension
84
+ @inventory.delete_if { |_ack_id, item| item.pulled_at < extension_time }
85
+ @wait_cond.broadcast
86
+ end
87
+ end
88
+
89
+ def count
90
+ synchronize do
91
+ @inventory.count
92
+ end
93
+ end
94
+
95
+ def total_bytesize
96
+ synchronize do
97
+ @inventory.values.sum(&:bytesize)
98
+ end
99
+ end
100
+
101
+ def empty?
102
+ synchronize do
103
+ @inventory.empty?
104
+ end
105
+ end
106
+
107
+ def start
108
+ @background_thread ||= Thread.new { background_run }
109
+
110
+ self
111
+ end
112
+
113
+ def stop
114
+ synchronize do
115
+ @stopped = true
116
+ @wait_cond.broadcast
117
+ end
118
+
119
+ self
120
+ end
121
+
122
+ def stopped?
123
+ synchronize { @stopped }
124
+ end
125
+
126
+ def full?
127
+ synchronize do
128
+ @inventory.count >= limit || @inventory.values.sum(&:bytesize) >= bytesize
129
+ end
130
+ end
131
+
132
+ protected
133
+
134
+ def background_run
135
+ delay_target = nil
136
+
137
+ until stopped?
138
+ if empty?
139
+ delay_target = nil
140
+
141
+ synchronize { @wait_cond.wait } # wait until broadcast
142
+ next
143
+ end
144
+
145
+ delay_target ||= calc_target
146
+ delay_gap = delay_target - Time.now
147
+
148
+ unless delay_gap.positive?
149
+ delay_target = calc_target
150
+ stream.renew_lease!
151
+ next
152
+ end
153
+
154
+ synchronize { @wait_cond.wait delay_gap }
155
+ end
156
+ end
157
+
158
+ def calc_target
159
+ Time.now + calc_delay
160
+ end
161
+
162
+ def calc_delay
163
+ delay = (stream.subscriber.deadline - 3) * rand(0.8..0.9)
164
+ delay = [delay, max_duration_per_lease_extension].min if max_duration_per_lease_extension.positive?
165
+ delay
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ Pubsub = PubSub unless const_defined? :Pubsub
172
+ end
173
+ end