google-cloud-spanner 2.1.0 → 2.2.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/google-cloud-spanner.rb +1 -0
- data/lib/google/cloud/spanner/convert.rb +9 -0
- data/lib/google/cloud/spanner/results.rb +94 -18
- data/lib/google/cloud/spanner/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01dd371ff37296529b691fd13961d7e7681e63480a88202b9e958a8c28bc480b
|
4
|
+
data.tar.gz: 9915fdf52be7508c55380b193a9586a35c702617080d3bf93a9f53b37b62be84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a34c4eeaaf84abe4d311350a155b22190c7dbc426a48719df4ad553692d841aa1a2d3a72d7f043b2fef7b3fa87a81cda69f965f5eef58a8ce17a77bf186a48e
|
7
|
+
data.tar.gz: 36062397079b8960916575b9188c0ad10f376d27b7d194a20e7f4c6e69f29eeb018b499576209bf1b2d2985725233db5de3e233ff840b5c93790d15b9b4204ab
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 2.2.0 / 2020-09-15
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* quota_project can be set via library configuration
|
8
|
+
* Support numeric type.
|
9
|
+
|
10
|
+
#### Bug Fixes
|
11
|
+
|
12
|
+
* retry or resume eos and rst_stream errors
|
13
|
+
|
3
14
|
### 2.1.0 / 2020-08-05
|
4
15
|
|
5
16
|
#### Features
|
data/lib/google-cloud-spanner.rb
CHANGED
@@ -174,6 +174,7 @@ Google::Cloud.configure.add_config! :spanner do |config|
|
|
174
174
|
allow_nil: true
|
175
175
|
config.add_alias! :keyfile, :credentials
|
176
176
|
config.add_field! :scope, default_scopes, match: [String, Array]
|
177
|
+
config.add_field! :quota_project, nil, match: String
|
177
178
|
config.add_field! :timeout, nil, match: Integer
|
178
179
|
config.add_field! :endpoint, "spanner.googleapis.com", match: String
|
179
180
|
config.add_field! :emulator_host, default_emulator, match: String, allow_nil: true
|
@@ -17,6 +17,7 @@ require "time"
|
|
17
17
|
require "date"
|
18
18
|
require "stringio"
|
19
19
|
require "base64"
|
20
|
+
require "bigdecimal"
|
20
21
|
require "google/cloud/spanner/data"
|
21
22
|
|
22
23
|
module Google
|
@@ -67,6 +68,9 @@ module Google
|
|
67
68
|
Google::Protobuf::Value.new bool_value: false
|
68
69
|
when Integer
|
69
70
|
Google::Protobuf::Value.new string_value: obj.to_s
|
71
|
+
# BigDecimal must be put before Numeric.
|
72
|
+
when BigDecimal
|
73
|
+
Google::Protobuf::Value.new string_value: obj.to_s("F")
|
70
74
|
when Numeric
|
71
75
|
if obj == Float::INFINITY
|
72
76
|
Google::Protobuf::Value.new string_value: "Infinity"
|
@@ -125,6 +129,9 @@ module Google
|
|
125
129
|
:BOOL
|
126
130
|
when Integer
|
127
131
|
:INT64
|
132
|
+
# BigDecimal must be put before Numeric.
|
133
|
+
when BigDecimal
|
134
|
+
:NUMERIC
|
128
135
|
when Numeric
|
129
136
|
:FLOAT64
|
130
137
|
when Time
|
@@ -214,6 +221,8 @@ module Google
|
|
214
221
|
end
|
215
222
|
when :STRUCT
|
216
223
|
Data.from_grpc value.list_value.values, type.struct_type.fields
|
224
|
+
when :NUMERIC
|
225
|
+
BigDecimal value.string_value
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|
@@ -41,6 +41,8 @@ module Google
|
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
class Results
|
44
|
+
RST_STREAM_INTERNAL_ERROR = "Received RST_STREAM".freeze
|
45
|
+
EOS_INTERNAL_ERROR = "Received unexpected EOS on DATA frame from server".freeze
|
44
46
|
##
|
45
47
|
# The read timestamp chosen for single-use snapshots (read-only
|
46
48
|
# transactions).
|
@@ -107,12 +109,24 @@ module Google
|
|
107
109
|
buffer_upper_bound = 10
|
108
110
|
chunked_value = nil
|
109
111
|
resume_token = nil
|
112
|
+
should_resume_request = false
|
113
|
+
should_retry_request = false
|
110
114
|
|
111
115
|
# Cannot call Enumerator#each because it won't return the first
|
112
116
|
# value that was already identified when calling Enumerator#peek.
|
113
117
|
# Iterate only using Enumerator#next and break on StopIteration.
|
114
118
|
loop do
|
115
119
|
begin
|
120
|
+
if should_resume_request
|
121
|
+
@enum = resume_request(resume_token)
|
122
|
+
buffered_responses = []
|
123
|
+
should_resume_request = false
|
124
|
+
elsif should_retry_request
|
125
|
+
@enum = retry_request()
|
126
|
+
buffered_responses = []
|
127
|
+
should_retry_request = false
|
128
|
+
end
|
129
|
+
|
116
130
|
grpc = @enum.next
|
117
131
|
# metadata should be set before the first iteration...
|
118
132
|
@metadata ||= grpc.metadata
|
@@ -143,28 +157,36 @@ module Google
|
|
143
157
|
# Flush the buffered responses now that they are all handled
|
144
158
|
buffered_responses = []
|
145
159
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
160
|
+
# TODO: once the generated client throws only Google Cloud errors, remove
|
161
|
+
# the GRPC errors from the rescue block
|
162
|
+
rescue GRPC::Aborted,
|
163
|
+
GRPC::Cancelled,
|
164
|
+
GRPC::DeadlineExceeded,
|
165
|
+
GRPC::Internal,
|
166
|
+
GRPC::ResourceExhausted,
|
167
|
+
GRPC::Unauthenticated,
|
168
|
+
GRPC::Unavailable,
|
169
|
+
GRPC::Core::CallError,
|
170
|
+
Google::Cloud::AbortedError,
|
171
|
+
Google::Cloud::CanceledError,
|
172
|
+
Google::Cloud::DeadlineExceededError,
|
173
|
+
Google::Cloud::InternalError,
|
174
|
+
Google::Cloud::ResourceExhaustedError,
|
175
|
+
Google::Cloud::UnauthenticatedError,
|
176
|
+
Google::Cloud::UnavailableError => err
|
154
177
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
178
|
+
if resumable?(resume_token)
|
179
|
+
should_resume_request = true
|
180
|
+
elsif retryable?(err)
|
181
|
+
should_retry_request = true
|
182
|
+
elsif err.is_a?(Google::Cloud::Error)
|
183
|
+
raise err
|
160
184
|
else
|
161
|
-
|
162
|
-
@session_path, @table, @columns,
|
163
|
-
@read_options.merge(resume_token: resume_token)
|
185
|
+
raise Google::Cloud::Error.from_error(err)
|
164
186
|
end
|
165
187
|
|
166
|
-
|
167
|
-
|
188
|
+
# TODO: once the generated client throws only Google Cloud errors, remove
|
189
|
+
# this rescue block (for GRPC::BadStatus)
|
168
190
|
rescue GRPC::BadStatus => err
|
169
191
|
raise Google::Cloud::Error.from_error(err)
|
170
192
|
rescue StopIteration
|
@@ -198,6 +220,60 @@ module Google
|
|
198
220
|
|
199
221
|
# rubocop:enable all
|
200
222
|
|
223
|
+
##
|
224
|
+
# @private
|
225
|
+
# Checks if a request can be resumed by inspecting the resume token
|
226
|
+
def resumable? resume_token
|
227
|
+
resume_token && !resume_token.empty?
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# @private
|
232
|
+
# Checks if a request can be retried. This is based on the error returned.
|
233
|
+
# Retryable errors are:
|
234
|
+
# - Unavailable error
|
235
|
+
# - Internal EOS error
|
236
|
+
# - Internal RST_STREAM error
|
237
|
+
def retryable? err
|
238
|
+
err.instance_of?(Google::Cloud::UnavailableError) ||
|
239
|
+
err.instance_of?(GRPC::Unavailable) ||
|
240
|
+
(err.instance_of?(Google::Cloud::InternalError) && err.message.include?(EOS_INTERNAL_ERROR)) ||
|
241
|
+
(err.instance_of?(GRPC::Internal) && err.details.include?(EOS_INTERNAL_ERROR)) ||
|
242
|
+
(err.instance_of?(Google::Cloud::InternalError) && err.message.include?(RST_STREAM_INTERNAL_ERROR)) ||
|
243
|
+
(err.instance_of?(GRPC::Internal) && err.details.include?(RST_STREAM_INTERNAL_ERROR))
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# @private
|
248
|
+
# Resumes a request, by re-executing it with a resume token.
|
249
|
+
def resume_request resume_token
|
250
|
+
if @execute_query_options
|
251
|
+
@service.execute_streaming_sql(
|
252
|
+
@session_path,
|
253
|
+
@sql,
|
254
|
+
@execute_query_options.merge(resume_token: resume_token)
|
255
|
+
)
|
256
|
+
else
|
257
|
+
@service.streaming_read_table(
|
258
|
+
@session_path,
|
259
|
+
@table,
|
260
|
+
@columns,
|
261
|
+
@read_options.merge(resume_token: resume_token)
|
262
|
+
)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
##
|
267
|
+
# @private
|
268
|
+
# Retries a request, by re-executing it from scratch.
|
269
|
+
def retry_request
|
270
|
+
if @execute_query_options
|
271
|
+
@service.execute_streaming_sql @session_path, @sql, @execute_query_options
|
272
|
+
else
|
273
|
+
@service.streaming_read_table @session_path, @table, @columns, @read_options
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
201
277
|
##
|
202
278
|
# @private
|
203
279
|
# Get row count from stats. This will be the exact row count for DML
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-spanner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-09-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-cloud-core
|
@@ -329,7 +329,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
329
329
|
- !ruby/object:Gem::Version
|
330
330
|
version: '0'
|
331
331
|
requirements: []
|
332
|
-
rubygems_version: 3.1.
|
332
|
+
rubygems_version: 3.1.4
|
333
333
|
signing_key:
|
334
334
|
specification_version: 4
|
335
335
|
summary: API Client library for Google Cloud Spanner API
|