google-cloud-firestore 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c1c6b4bcea222f6ed81150700b9d6c969fc70eeb8492db0ed69db1bb43f62cb
4
- data.tar.gz: 50bbd220cf388af656606d99948477d47f9a1fa3d41ab479f6fcaa32f32e909d
3
+ metadata.gz: 12a9c7f721487eef84a1d703f77f0b2f56aea624fc9c6e1052be059c49437a6f
4
+ data.tar.gz: 76d354bb9933a7a83ef6163fef5bd37da82808786f05d06a83f54dc605ca1154
5
5
  SHA512:
6
- metadata.gz: d1a810ae1cd779858ad8762dacd08765b2daf06b1de8ce13dc675b79ef7c6696c3bbda34d7593a6087e2189aebd2e23090bd89d11da8753f1751726270a61391
7
- data.tar.gz: af77949c47636ca6e65ca14224fa5270a9f3daa4c00fd236e19780273e35593c0986ba5e5a0d601a6f107cbdc5482db51ca002841ee8cbf21acbd9ac752a93ee
6
+ metadata.gz: b8e403df8684221a0521432017c511f8b0c4d174c97c95129f7952e6751914093fe692585127d2f0a267f9776b9a464062bd10e3f3a7d9aa7c772edcddde8d2e
7
+ data.tar.gz: bd858f3f1c199b835ce22f567068af585f9ce41d2cd9da6811f5d06bbcc45ab1aadaa40575d1684bb2245d691c90589df420343a0233039f860030513037de75
@@ -1,5 +1,15 @@
1
1
  # Release History
2
2
 
3
+ ### 2.3.0 / 2020-09-30
4
+
5
+ #### Features
6
+
7
+ * Add error callbacks for listener threads
8
+ * Add DocumentListener#last_error
9
+ * Add DocumentListener#on_error
10
+ * Add QueryListener#last_error
11
+ * Add QueryListener#on_error
12
+
3
13
  ### 2.2.0 / 2020-09-17
4
14
 
5
15
  #### Features
@@ -14,11 +14,14 @@
14
14
 
15
15
 
16
16
  require "google/cloud/firestore/watch/listener"
17
+ require "monitor"
17
18
 
18
19
  module Google
19
20
  module Cloud
20
21
  module Firestore
21
22
  ##
23
+ # # DocumentListener
24
+ #
22
25
  # An ongoing listen operation on a document reference. This is returned by
23
26
  # calling {DocumentReference#listen}.
24
27
  #
@@ -31,25 +34,28 @@ module Google
31
34
  # nyc_ref = firestore.doc "cities/NYC"
32
35
  #
33
36
  # listener = nyc_ref.listen do |snapshot|
34
- # puts "The population of #{snapshot[:name]} "
35
- # puts "is #{snapshot[:population]}."
37
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
36
38
  # end
37
39
  #
38
40
  # # When ready, stop the listen operation and close the stream.
39
41
  # listener.stop
40
42
  #
41
43
  class DocumentListener
44
+ include MonitorMixin
42
45
  ##
43
46
  # @private
44
47
  # Creates the watch stream and listener object.
45
48
  def initialize doc_ref, &callback
49
+ super() # to init MonitorMixin
50
+
46
51
  @doc_ref = doc_ref
47
52
  raise ArgumentError if @doc_ref.nil?
48
53
 
49
54
  @callback = callback
50
55
  raise ArgumentError if @callback.nil?
56
+ @error_callbacks = []
51
57
 
52
- @listener = Watch::Listener.for_doc_ref doc_ref do |query_snp|
58
+ @listener = Watch::Listener.for_doc_ref self, doc_ref do |query_snp|
53
59
  doc_snp = query_snp.docs.find { |doc| doc.path == @doc_ref.path }
54
60
 
55
61
  if doc_snp.nil?
@@ -80,8 +86,7 @@ module Google
80
86
  # nyc_ref = firestore.doc "cities/NYC"
81
87
  #
82
88
  # listener = nyc_ref.listen do |snapshot|
83
- # puts "The population of #{snapshot[:name]} "
84
- # puts "is #{snapshot[:population]}."
89
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
85
90
  # end
86
91
  #
87
92
  # # When ready, stop the listen operation and close the stream.
@@ -103,8 +108,7 @@ module Google
103
108
  # nyc_ref = firestore.doc "cities/NYC"
104
109
  #
105
110
  # listener = nyc_ref.listen do |snapshot|
106
- # puts "The population of #{snapshot[:name]} "
107
- # puts "is #{snapshot[:population]}."
111
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
108
112
  # end
109
113
  #
110
114
  # # Checks if the listener is stopped.
@@ -119,6 +123,81 @@ module Google
119
123
  def stopped?
120
124
  @listener.stopped?
121
125
  end
126
+
127
+ ##
128
+ # Register to be notified of errors when raised.
129
+ #
130
+ # If an unhandled error has occurred the listener will attempt to
131
+ # recover from the error and resume listening.
132
+ #
133
+ # Multiple error handlers can be added.
134
+ #
135
+ # @yield [callback] The block to be called when an error is raised.
136
+ # @yieldparam [Exception] error The error raised.
137
+ #
138
+ # @example
139
+ # require "google/cloud/firestore"
140
+ #
141
+ # firestore = Google::Cloud::Firestore.new
142
+ #
143
+ # # Get a document reference
144
+ # nyc_ref = firestore.doc "cities/NYC"
145
+ #
146
+ # listener = nyc_ref.listen do |snapshot|
147
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
148
+ # end
149
+ #
150
+ # # Register to be notified when unhandled errors occur.
151
+ # listener.on_error do |error|
152
+ # puts error
153
+ # end
154
+ #
155
+ # # When ready, stop the listen operation and close the stream.
156
+ # listener.stop
157
+ #
158
+ def on_error &block
159
+ raise ArgumentError, "on_error must be called with a block" unless block_given?
160
+ synchronize { @error_callbacks << block }
161
+ end
162
+
163
+ ##
164
+ # The most recent unhandled error to occur while listening for changes.
165
+ #
166
+ # If an unhandled error has occurred the listener will attempt to
167
+ # recover from the error and resume listening.
168
+ #
169
+ # @return [Exception, nil] error The most recent error raised.
170
+ #
171
+ # @example
172
+ # require "google/cloud/firestore"
173
+ #
174
+ # firestore = Google::Cloud::Firestore.new
175
+ #
176
+ # # Get a document reference
177
+ # nyc_ref = firestore.doc "cities/NYC"
178
+ #
179
+ # listener = nyc_ref.listen do |snapshot|
180
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
181
+ # end
182
+ #
183
+ # # If an error was raised, it can be retrieved here:
184
+ # listener.last_error #=> nil
185
+ #
186
+ # # When ready, stop the listen operation and close the stream.
187
+ # listener.stop
188
+ #
189
+ def last_error
190
+ synchronize { @last_error }
191
+ end
192
+
193
+ # @private Pass the error to user-provided error callbacks.
194
+ def error! error
195
+ error_callbacks = synchronize do
196
+ @last_error = error
197
+ @error_callbacks.dup
198
+ end
199
+ error_callbacks.each { |error_callback| error_callback.call error }
200
+ end
122
201
  end
123
202
  end
124
203
  end
@@ -168,8 +168,7 @@ module Google
168
168
  # nyc_ref = firestore.doc "cities/NYC"
169
169
  #
170
170
  # listener = nyc_ref.listen do |snapshot|
171
- # puts "The population of #{snapshot[:name]} "
172
- # puts "is #{snapshot[:population]}."
171
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
173
172
  # end
174
173
  #
175
174
  # # When ready, stop the listen operation and close the stream.
@@ -53,8 +53,7 @@ module Google
53
53
  # nyc_ref = firestore.doc "cities/NYC"
54
54
  #
55
55
  # listener = nyc_ref.listen do |snapshot|
56
- # puts "The population of #{snapshot[:name]} "
57
- # puts "is #{snapshot[:population]}."
56
+ # puts "The population of #{snapshot[:name]} is #{snapshot[:population]}."
58
57
  # end
59
58
  #
60
59
  # # When ready, stop the listen operation and close the stream.
@@ -41,17 +41,21 @@ module Google
41
41
  # listener.stop
42
42
  #
43
43
  class QueryListener
44
+ include MonitorMixin
44
45
  ##
45
46
  # @private
46
47
  # Creates the watch stream and listener object.
47
48
  def initialize query, &callback
49
+ super() # to init MonitorMixin
50
+
48
51
  @query = query
49
52
  raise ArgumentError if @query.nil?
50
53
 
51
54
  @callback = callback
52
55
  raise ArgumentError if @callback.nil?
56
+ @error_callbacks = []
53
57
 
54
- @listener = Watch::Listener.for_query query, &callback
58
+ @listener = Watch::Listener.for_query self, query, &callback
55
59
  end
56
60
 
57
61
  ##
@@ -112,6 +116,83 @@ module Google
112
116
  def stopped?
113
117
  @listener.stopped?
114
118
  end
119
+
120
+ ##
121
+ # Register to be notified of errors when raised.
122
+ #
123
+ # If an unhandled error has occurred the listener will attempt to
124
+ # recover from the error and resume listening.
125
+ #
126
+ # Multiple error handlers can be added.
127
+ #
128
+ # @yield [callback] The block to be called when an error is raised.
129
+ # @yieldparam [Exception] error The error raised.
130
+ #
131
+ # @example
132
+ # require "google/cloud/firestore"
133
+ #
134
+ # firestore = Google::Cloud::Firestore.new
135
+ #
136
+ # # Create a query
137
+ # query = firestore.col(:cities).order(:population, :desc)
138
+ #
139
+ # listener = query.listen do |snapshot|
140
+ # puts "The query snapshot has #{snapshot.docs.count} documents "
141
+ # puts "and has #{snapshot.changes.count} changes."
142
+ # end
143
+ #
144
+ # # Register to be notified when unhandled errors occur.
145
+ # listener.on_error do |error|
146
+ # puts error
147
+ # end
148
+ #
149
+ # # When ready, stop the listen operation and close the stream.
150
+ # listener.stop
151
+ #
152
+ def on_error &block
153
+ raise ArgumentError, "on_error must be called with a block" unless block_given?
154
+ synchronize { @error_callbacks << block }
155
+ end
156
+
157
+ ##
158
+ # The most recent unhandled error to occur while listening for changes.
159
+ #
160
+ # If an unhandled error has occurred the listener will attempt to
161
+ # recover from the error and resume listening.
162
+ #
163
+ # @return [Exception, nil] error The most recent error raised.
164
+ #
165
+ # @example
166
+ # require "google/cloud/firestore"
167
+ #
168
+ # firestore = Google::Cloud::Firestore.new
169
+ #
170
+ # # Create a query
171
+ # query = firestore.col(:cities).order(:population, :desc)
172
+ #
173
+ # listener = query.listen do |snapshot|
174
+ # puts "The query snapshot has #{snapshot.docs.count} documents "
175
+ # puts "and has #{snapshot.changes.count} changes."
176
+ # end
177
+ #
178
+ # # If an error was raised, it can be retrieved here:
179
+ # listener.last_error #=> nil
180
+ #
181
+ # # When ready, stop the listen operation and close the stream.
182
+ # listener.stop
183
+ #
184
+ def last_error
185
+ synchronize { @last_error }
186
+ end
187
+
188
+ # @private Pass the error to user-provided error callbacks.
189
+ def error! error
190
+ error_callbacks = synchronize do
191
+ @last_error = error
192
+ @error_callbacks.dup
193
+ end
194
+ error_callbacks.each { |error_callback| error_callback.call error }
195
+ end
115
196
  end
116
197
  end
117
198
  end
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Firestore
19
- VERSION = "2.2.0".freeze
19
+ VERSION = "2.3.0".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -30,7 +30,7 @@ module Google
30
30
  class Listener
31
31
  include MonitorMixin
32
32
 
33
- def self.for_doc_ref doc_ref, &callback
33
+ def self.for_doc_ref parent, doc_ref, &callback
34
34
  raise ArgumentError if doc_ref.nil?
35
35
  raise ArgumentError if callback.nil?
36
36
 
@@ -44,10 +44,10 @@ module Google
44
44
  )
45
45
  )
46
46
 
47
- new nil, doc_ref, doc_ref.client, init_listen_req, &callback
47
+ new parent, nil, doc_ref, doc_ref.client, init_listen_req, &callback
48
48
  end
49
49
 
50
- def self.for_query query, &callback
50
+ def self.for_query parent, query, &callback
51
51
  raise ArgumentError if query.nil?
52
52
  raise ArgumentError if callback.nil?
53
53
 
@@ -61,12 +61,13 @@ module Google
61
61
  )
62
62
  )
63
63
 
64
- new query, nil, query.client, init_listen_req, &callback
64
+ new parent, query, nil, query.client, init_listen_req, &callback
65
65
  end
66
66
 
67
- def initialize query, doc_ref, client, init_listen_req, &callback
67
+ def initialize parent, query, doc_ref, client, init_listen_req, &callback
68
68
  super() # to init MonitorMixin
69
69
 
70
+ @parent = parent
70
71
  @query = query
71
72
  @doc_ref = doc_ref
72
73
  @client = client
@@ -119,6 +120,8 @@ module Google
119
120
 
120
121
  def send_callback query_snp
121
122
  @callback.call query_snp
123
+ rescue StandardError => e
124
+ @parent.error! e
122
125
  end
123
126
 
124
127
  def start_listening!
@@ -270,25 +273,29 @@ module Google
270
273
  @request_queue.push self
271
274
  rescue GRPC::Cancelled, GRPC::DeadlineExceeded, GRPC::Internal,
272
275
  GRPC::ResourceExhausted, GRPC::Unauthenticated,
273
- GRPC::Unavailable, GRPC::Core::CallError
276
+ GRPC::Unavailable, GRPC::Core::CallError => e
274
277
  # Restart the stream with an incremental back for a retriable error.
275
278
  # Also when GRPC raises the internal CallError.
276
279
 
277
- # Re-raise if retried more than the max
278
- raise err if @backoff[:current] > @backoff[:max]
279
-
280
- # Sleep with incremental backoff before restarting
281
- sleep @backoff[:delay]
280
+ # Raise if retried more than the max
281
+ if @backoff[:current] > @backoff[:max]
282
+ @parent.error! e
283
+ raise e
284
+ else
285
+ # Sleep with incremental backoff before restarting
286
+ sleep @backoff[:delay]
282
287
 
283
- # Update increment backoff delay and retry counter
284
- @backoff[:delay] *= @backoff[:mod]
285
- @backoff[:current] += 1
288
+ # Update increment backoff delay and retry counter
289
+ @backoff[:delay] *= @backoff[:mod]
290
+ @backoff[:current] += 1
286
291
 
287
- retry
292
+ retry
293
+ end
288
294
  rescue RestartStream
289
295
  retry
290
296
  rescue StandardError => e
291
- raise Google::Cloud::Error.from_error(e)
297
+ @parent.error! e
298
+ raise e
292
299
  end
293
300
  end
294
301
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-firestore
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-17 00:00:00.000000000 Z
11
+ date: 2020-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-cloud-core