google-gax 0.10.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/google/gax/api_callable.rb +7 -6
- data/lib/google/gax/errors.rb +73 -0
- data/lib/google/gax/grpc.rb +2 -2
- data/lib/google/gax/operation.rb +1 -1
- data/lib/google/gax/path_template.rb +1 -1
- data/lib/google/gax/util.rb +36 -4
- data/lib/google/gax/version.rb +1 -1
- data/lib/google/longrunning/operations_client.rb +10 -19
- data/spec/fixtures/fixture.proto +4 -0
- data/spec/fixtures/fixture_file.txt +1 -0
- data/spec/fixtures/fixture_pb.rb +3 -0
- data/spec/google/gax/api_callable_spec.rb +2 -2
- data/spec/google/gax/bundling_spec.rb +1 -1
- data/spec/google/gax/error_spec.rb +100 -3
- data/spec/google/gax/util_spec.rb +61 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87b2e27818073928a99f7edc7a49ab31a1ff05a6
|
4
|
+
data.tar.gz: bbe86ff3f6584127ace5d22509c59bb1be0b7e60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 108eb512cbf772cb7b0fd1196b9676ef594bb7ecbdab2038f4e307e9e1d20289b7a108d4031a28545c8110468adc23c2ffbccdafa57e311a00f152a6afe32db6
|
7
|
+
data.tar.gz: 37fb30807ae24551812160303d18ead970587dacb30c53e1a01708eee42ac77e6b4ff5c68b322470c34f0e8a0f04ac98505c4ecb1aab00632bdd31a274cbdd08
|
@@ -168,7 +168,7 @@ module Google
|
|
168
168
|
# @yield [Page] Gives the pages in the stream.
|
169
169
|
# @raise [GaxError] if it's not started yet.
|
170
170
|
def each_page
|
171
|
-
raise GaxError
|
171
|
+
raise GaxError.new('not started!') unless started?
|
172
172
|
yield @page
|
173
173
|
loop do
|
174
174
|
break unless next_page?
|
@@ -254,8 +254,9 @@ module Google
|
|
254
254
|
end
|
255
255
|
begin
|
256
256
|
api_caller.call(api_call, request, this_settings)
|
257
|
-
rescue *settings.errors
|
258
|
-
|
257
|
+
rescue *settings.errors => e
|
258
|
+
error_class = Google::Gax.from_error e
|
259
|
+
raise error_class.new('RPC failed')
|
259
260
|
end
|
260
261
|
end
|
261
262
|
end
|
@@ -348,15 +349,15 @@ module Google
|
|
348
349
|
rescue => exception
|
349
350
|
unless exception.respond_to?(:code) &&
|
350
351
|
retry_options.retry_codes.include?(exception.code)
|
351
|
-
raise RetryError
|
352
|
-
'was not classified as transient'
|
352
|
+
raise RetryError.new('Exception occurred in retry method that ' \
|
353
|
+
'was not classified as transient')
|
353
354
|
end
|
354
355
|
sleep(rand(delay) / MILLIS_PER_SECOND)
|
355
356
|
now = Time.now
|
356
357
|
delay = [delay * delay_mult, max_delay].min
|
357
358
|
timeout = [timeout * timeout_mult, max_timeout, deadline - now].min
|
358
359
|
if now >= deadline
|
359
|
-
raise RetryError
|
360
|
+
raise RetryError.new('Retry total timeout exceeded with exception')
|
360
361
|
end
|
361
362
|
retry
|
362
363
|
end
|
data/lib/google/gax/errors.rb
CHANGED
@@ -71,8 +71,81 @@ module Google
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def from_error(error)
|
75
|
+
if error.respond_to? :code
|
76
|
+
grpc_error_class_for error.code
|
77
|
+
else
|
78
|
+
GaxError
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
74
82
|
# Indicates an error during automatic GAX retrying.
|
75
83
|
class RetryError < GaxError
|
76
84
|
end
|
85
|
+
|
86
|
+
# Errors corresponding to standard HTTP/gRPC statuses.
|
87
|
+
class CanceledError < GaxError
|
88
|
+
end
|
89
|
+
|
90
|
+
class UnknownError < GaxError
|
91
|
+
end
|
92
|
+
|
93
|
+
class InvalidArgumentError < GaxError
|
94
|
+
end
|
95
|
+
|
96
|
+
class DeadlineExceededError < GaxError
|
97
|
+
end
|
98
|
+
|
99
|
+
class NotFoundError < GaxError
|
100
|
+
end
|
101
|
+
|
102
|
+
class AlreadyExistsError < GaxError
|
103
|
+
end
|
104
|
+
|
105
|
+
class PermissionDeniedError < GaxError
|
106
|
+
end
|
107
|
+
|
108
|
+
class ResourceExhaustedError < GaxError
|
109
|
+
end
|
110
|
+
|
111
|
+
class FailedPreconditionError < GaxError
|
112
|
+
end
|
113
|
+
|
114
|
+
class AbortedError < GaxError
|
115
|
+
end
|
116
|
+
|
117
|
+
class OutOfRangeError < GaxError
|
118
|
+
end
|
119
|
+
|
120
|
+
class UnimplementedError < GaxError
|
121
|
+
end
|
122
|
+
|
123
|
+
class InternalError < GaxError
|
124
|
+
end
|
125
|
+
|
126
|
+
class UnavailableError < GaxError
|
127
|
+
end
|
128
|
+
|
129
|
+
class DataLossError < GaxError
|
130
|
+
end
|
131
|
+
|
132
|
+
class UnauthenticatedError < GaxError
|
133
|
+
end
|
134
|
+
|
135
|
+
# @private Identify the subclass for a gRPC error
|
136
|
+
# Note: ported from
|
137
|
+
# https:/g/github.com/GoogleCloudPlatform/google-cloud-ruby/blob/master/google-cloud-core/lib/google/cloud/errors.rb
|
138
|
+
def self.grpc_error_class_for(grpc_error_code)
|
139
|
+
# The gRPC status code 0 is for a successful response.
|
140
|
+
# So there is no error subclass for a 0 status code, use current class.
|
141
|
+
[GaxError, CanceledError, UnknownError, InvalidArgumentError,
|
142
|
+
DeadlineExceededError, NotFoundError, AlreadyExistsError,
|
143
|
+
PermissionDeniedError, ResourceExhaustedError, FailedPreconditionError,
|
144
|
+
AbortedError, OutOfRangeError, UnimplementedError, InternalError,
|
145
|
+
UnavailableError, DataLossError,
|
146
|
+
UnauthenticatedError][grpc_error_code] || GaxError
|
147
|
+
end
|
148
|
+
|
149
|
+
module_function :from_error
|
77
150
|
end
|
78
151
|
end
|
data/lib/google/gax/grpc.rb
CHANGED
@@ -136,9 +136,9 @@ module Google
|
|
136
136
|
if (channel && chan_creds) ||
|
137
137
|
(channel && updater_proc) ||
|
138
138
|
(chan_creds && updater_proc)
|
139
|
-
raise ArgumentError
|
139
|
+
raise ArgumentError.new('Only one of channel, chan_creds, and ' \
|
140
140
|
'updater_proc should be passed into ' \
|
141
|
-
'Google::Gax::Grpc#create_stub.'
|
141
|
+
'Google::Gax::Grpc#create_stub.')
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
data/lib/google/gax/operation.rb
CHANGED
@@ -254,7 +254,7 @@ module Google
|
|
254
254
|
until done?
|
255
255
|
sleep(delay)
|
256
256
|
if Time.now >= deadline
|
257
|
-
raise RetryError
|
257
|
+
raise RetryError.new('Retry total timeout exceeded with exception')
|
258
258
|
end
|
259
259
|
delay = [delay * delay_multiplier, max_delay].min
|
260
260
|
reload!
|
@@ -175,7 +175,7 @@ module Google
|
|
175
175
|
literal_sym = segment.literal.to_sym
|
176
176
|
unless bindings.key?(literal_sym)
|
177
177
|
msg = "Value for key #{segment.literal} is not provided"
|
178
|
-
raise(
|
178
|
+
raise ArgumentError.new(msg)
|
179
179
|
end
|
180
180
|
out.concat(PathTemplate.new(bindings[literal_sym]).segments)
|
181
181
|
binding = true
|
data/lib/google/gax/util.rb
CHANGED
@@ -27,6 +27,8 @@
|
|
27
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
|
30
|
+
require 'google/protobuf/timestamp_pb'
|
31
|
+
|
30
32
|
module Google
|
31
33
|
# Gax defines Google API extensions
|
32
34
|
module Gax
|
@@ -54,8 +56,9 @@ module Google
|
|
54
56
|
|
55
57
|
# Sanity check: input must be a Hash
|
56
58
|
unless hash.is_a? Hash
|
57
|
-
raise ArgumentError
|
58
|
-
|
59
|
+
raise ArgumentError.new(
|
60
|
+
"Value #{hash} must be a Hash or a #{message_class.name}"
|
61
|
+
)
|
59
62
|
end
|
60
63
|
hash = coerce_submessages(hash, message_class)
|
61
64
|
message_class.new(hash)
|
@@ -79,6 +82,9 @@ module Google
|
|
79
82
|
field_descriptor = message_descriptor.lookup(key.to_s)
|
80
83
|
if field_descriptor && field_descriptor.type == :message
|
81
84
|
coerced[key] = coerce_submessage(val, field_descriptor)
|
85
|
+
elsif field_descriptor && field_descriptor.type == :bytes &&
|
86
|
+
(val.is_a?(IO) || val.is_a?(StringIO))
|
87
|
+
coerced[key] = val.binmode.read
|
82
88
|
else
|
83
89
|
# `google/protobuf` should throw an error if no field descriptor is
|
84
90
|
# found. Simply pass through.
|
@@ -101,6 +107,9 @@ module Google
|
|
101
107
|
def coerce_submessage(val, field_descriptor)
|
102
108
|
if (field_descriptor.label == :repeated) && !(map_field? field_descriptor)
|
103
109
|
coerce_array(val, field_descriptor)
|
110
|
+
elsif field_descriptor.subtype.msgclass == Google::Protobuf::Timestamp &&
|
111
|
+
val.is_a?(Time)
|
112
|
+
time_to_timestamp(val)
|
104
113
|
else
|
105
114
|
coerce(val, field_descriptor)
|
106
115
|
end
|
@@ -118,7 +127,7 @@ module Google
|
|
118
127
|
# @return [Array<Object>] The coerced version of the given values.
|
119
128
|
def coerce_array(array, field_descriptor)
|
120
129
|
unless array.is_a? Array
|
121
|
-
raise ArgumentError
|
130
|
+
raise ArgumentError.new('Value ' + array.to_s + ' must be an array')
|
122
131
|
end
|
123
132
|
array.map do |val|
|
124
133
|
coerce(val, field_descriptor)
|
@@ -150,8 +159,31 @@ module Google
|
|
150
159
|
to_proto(val, field_descriptor.subtype.msgclass)
|
151
160
|
end
|
152
161
|
|
162
|
+
# Utility for converting a Google::Protobuf::Timestamp instance to a Ruby
|
163
|
+
# time.
|
164
|
+
#
|
165
|
+
# @param timestamp [Google::Protobuf::Timestamp] The timestamp to be
|
166
|
+
# converted.
|
167
|
+
#
|
168
|
+
# @return [Time] The converted Time.
|
169
|
+
def timestamp_to_time(timestamp)
|
170
|
+
Time.at(timestamp.nanos * 10**-9 + timestamp.seconds)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Utility for converting a Ruby Time instance to a
|
174
|
+
# Google::Protobuf::Timestamp.
|
175
|
+
#
|
176
|
+
# @param time [Time] The Time to be converted.
|
177
|
+
#
|
178
|
+
# @return [Google::Protobuf::Timestamp] The converted
|
179
|
+
# Google::Protobuf::Timestamp.
|
180
|
+
def time_to_timestamp(time)
|
181
|
+
Google::Protobuf::Timestamp.new(seconds: time.to_i, nanos: time.nsec)
|
182
|
+
end
|
183
|
+
|
153
184
|
module_function :to_proto, :coerce_submessages, :coerce_submessage,
|
154
|
-
:coerce_array, :coerce, :map_field
|
185
|
+
:coerce_array, :coerce, :map_field?, :timestamp_to_time,
|
186
|
+
:time_to_timestamp
|
155
187
|
private_class_method :coerce_submessages, :coerce_submessage, :coerce_array,
|
156
188
|
:coerce, :map_field?
|
157
189
|
end
|
data/lib/google/gax/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2017, Google
|
1
|
+
# Copyright 2017, Google LLC All rights reserved.
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions are
|
@@ -10,7 +10,7 @@
|
|
10
10
|
# copyright notice, this list of conditions and the following disclaimer
|
11
11
|
# in the documentation and/or other materials provided with the
|
12
12
|
# distribution.
|
13
|
-
# * Neither the name of Google
|
13
|
+
# * Neither the name of Google LLC nor the names of its
|
14
14
|
# contributors may be used to endorse or promote products derived from
|
15
15
|
# this software without specific prior written permission.
|
16
16
|
#
|
@@ -83,6 +83,7 @@ module Google
|
|
83
83
|
ALL_SCOPES = [
|
84
84
|
].freeze
|
85
85
|
|
86
|
+
|
86
87
|
# @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel, GRPC::Core::ChannelCredentials, Proc]
|
87
88
|
# Provides the means for authenticating requests made by the client. This parameter can
|
88
89
|
# be many types.
|
@@ -108,11 +109,6 @@ module Google
|
|
108
109
|
# @param timeout [Numeric]
|
109
110
|
# The default timeout, in seconds, for calls made through this client.
|
110
111
|
def initialize \
|
111
|
-
service_path: self.class::SERVICE_ADDRESS,
|
112
|
-
port: self.class::DEFAULT_SERVICE_PORT,
|
113
|
-
channel: nil,
|
114
|
-
chan_creds: nil,
|
115
|
-
updater_proc: nil,
|
116
112
|
credentials: nil,
|
117
113
|
scopes: ALL_SCOPES,
|
118
114
|
client_config: {},
|
@@ -125,17 +121,6 @@ module Google
|
|
125
121
|
require "google/gax/grpc"
|
126
122
|
require "google/longrunning/operations_services_pb"
|
127
123
|
|
128
|
-
if channel || chan_creds || updater_proc
|
129
|
-
warn "The `channel`, `chan_creds`, and `updater_proc` parameters will be removed " \
|
130
|
-
"on 2017/09/08"
|
131
|
-
credentials ||= channel
|
132
|
-
credentials ||= chan_creds
|
133
|
-
credentials ||= updater_proc
|
134
|
-
end
|
135
|
-
if port != DEFAULT_SERVICE_PORT
|
136
|
-
warn "the `port` parameter is deprecated and will be removed"
|
137
|
-
end
|
138
|
-
|
139
124
|
credentials ||= Google::Auth::Credentials.default(scopes: scopes)
|
140
125
|
|
141
126
|
if credentials.is_a?(String) || credentials.is_a?(Hash)
|
@@ -154,9 +139,11 @@ module Google
|
|
154
139
|
updater_proc = credentials.updater_proc
|
155
140
|
end
|
156
141
|
|
142
|
+
package_version = Gem.loaded_specs['google-gax'].version.version
|
143
|
+
|
157
144
|
google_api_client = "gl-ruby/#{RUBY_VERSION}"
|
158
145
|
google_api_client << " #{lib_name}/#{lib_version}" if lib_name
|
159
|
-
google_api_client << " gapic
|
146
|
+
google_api_client << " gapic/#{package_version} gax/#{Google::Gax::VERSION}"
|
160
147
|
google_api_client << " grpc/#{GRPC::VERSION}"
|
161
148
|
google_api_client.freeze
|
162
149
|
|
@@ -176,6 +163,10 @@ module Google
|
|
176
163
|
kwargs: headers
|
177
164
|
)
|
178
165
|
end
|
166
|
+
|
167
|
+
# Allow overriding the service path/port in subclasses.
|
168
|
+
service_path = self.class::SERVICE_ADDRESS
|
169
|
+
port = self.class::DEFAULT_SERVICE_PORT
|
179
170
|
@operations_stub = Google::Gax::Grpc.create_stub(
|
180
171
|
service_path,
|
181
172
|
port,
|
data/spec/fixtures/fixture.proto
CHANGED
@@ -15,6 +15,8 @@ syntax = "proto3";
|
|
15
15
|
|
16
16
|
package google.protobuf;
|
17
17
|
|
18
|
+
import "google/protobuf/timestamp.proto";
|
19
|
+
|
18
20
|
message Request {
|
19
21
|
string name = 1;
|
20
22
|
User user = 2;
|
@@ -29,6 +31,8 @@ message User {
|
|
29
31
|
UserType type = 2;
|
30
32
|
repeated Post posts = 3;
|
31
33
|
map<string, string> map_field = 4;
|
34
|
+
bytes bytes_field = 5;
|
35
|
+
google.protobuf.Timestamp timestamp = 6;
|
32
36
|
}
|
33
37
|
|
34
38
|
message Post {
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a text file.
|
data/spec/fixtures/fixture_pb.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'google/protobuf'
|
5
5
|
|
6
|
+
require 'google/protobuf/timestamp_pb'
|
6
7
|
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
8
|
add_message "google.protobuf.Request" do
|
8
9
|
optional :name, :string, 1
|
@@ -13,6 +14,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
13
14
|
optional :type, :enum, 2, "google.protobuf.User.UserType"
|
14
15
|
repeated :posts, :message, 3, "google.protobuf.Post"
|
15
16
|
map :map_field, :string, :string, 4
|
17
|
+
optional :bytes_field, :bytes, 5
|
18
|
+
optional :timestamp, :message, 6, "google.protobuf.Timestamp"
|
16
19
|
end
|
17
20
|
add_enum "google.protobuf.User.UserType" do
|
18
21
|
value :UNSPECIFIED, 0
|
@@ -39,8 +39,8 @@ class CustomException < StandardError
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
FAKE_STATUS_CODE_1 =
|
43
|
-
FAKE_STATUS_CODE_2 =
|
42
|
+
FAKE_STATUS_CODE_1 = 1
|
43
|
+
FAKE_STATUS_CODE_2 = 2
|
44
44
|
|
45
45
|
# Google::Gax::CallSettings is private, only accessible in the module context.
|
46
46
|
# For testing purpose, this makes a toplevel ::CallSettings point to the same
|
@@ -67,7 +67,7 @@ describe Google::Gax::GaxError do
|
|
67
67
|
it 'presents GRPC::BadStatus values' do
|
68
68
|
error = wrapped_badstatus(3, 'invalid')
|
69
69
|
|
70
|
-
expect(error).to
|
70
|
+
expect(error).to be_a_kind_of(Google::Gax::GaxError)
|
71
71
|
expect(error.message).to eq('GaxError 3:invalid, caused by 3:invalid')
|
72
72
|
expect(error.code).to eq(3)
|
73
73
|
expect(error.details).to eq('invalid')
|
@@ -93,7 +93,7 @@ describe Google::Gax::GaxError do
|
|
93
93
|
'grpc-status-details-bin' => encoded_status_detail }
|
94
94
|
error = wrapped_badstatus(1, 'cancelled', metadata)
|
95
95
|
|
96
|
-
expect(error).to
|
96
|
+
expect(error).to be_a_kind_of(Google::Gax::GaxError)
|
97
97
|
expect(error.message).to eq('GaxError 1:cancelled, caused by 1:cancelled')
|
98
98
|
expect(error.code).to eq(1)
|
99
99
|
expect(error.details).to eq('cancelled')
|
@@ -108,10 +108,107 @@ describe Google::Gax::GaxError do
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
describe '#from_error' do
|
112
|
+
it 'identifies CanceledError' do
|
113
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(1, 'cancelled')
|
114
|
+
expect(mapped_error).to eq Google::Gax::CanceledError
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'identifies UnknownError' do
|
118
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(2, 'unknown')
|
119
|
+
expect(mapped_error).to eq Google::Gax::UnknownError
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'identifies InvalidArgumentError' do
|
123
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(3, 'invalid')
|
124
|
+
expect(mapped_error).to eq Google::Gax::InvalidArgumentError
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'identifies DeadlineExceededError' do
|
128
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(4, 'exceeded')
|
129
|
+
expect(mapped_error).to eq Google::Gax::DeadlineExceededError
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'identifies NotFoundError' do
|
133
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(5, 'not found')
|
134
|
+
expect(mapped_error).to eq Google::Gax::NotFoundError
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'identifies AlreadyExistsError' do
|
138
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(6, 'exists')
|
139
|
+
expect(mapped_error).to eq Google::Gax::AlreadyExistsError
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'identifies PermissionDeniedError' do
|
143
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(7, 'denied')
|
144
|
+
expect(mapped_error).to eq Google::Gax::PermissionDeniedError
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'identifies ResourceExhaustedError' do
|
148
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(8, 'exhausted')
|
149
|
+
expect(mapped_error).to eq Google::Gax::ResourceExhaustedError
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'identifies FailedPreconditionError' do
|
153
|
+
mapped_error =
|
154
|
+
Google::Gax.from_error GRPC::BadStatus.new(9, 'precondition')
|
155
|
+
expect(mapped_error).to eq Google::Gax::FailedPreconditionError
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'identifies AbortedError' do
|
159
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(10, 'aborted')
|
160
|
+
expect(mapped_error).to eq Google::Gax::AbortedError
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'identifies OutOfRangeError' do
|
164
|
+
mapped_error =
|
165
|
+
Google::Gax.from_error GRPC::BadStatus.new(11, 'out of range')
|
166
|
+
expect(mapped_error).to eq Google::Gax::OutOfRangeError
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'identifies UnimplementedError' do
|
170
|
+
mapped_error =
|
171
|
+
Google::Gax.from_error GRPC::BadStatus.new(12, 'unimplemented')
|
172
|
+
expect(mapped_error).to eq Google::Gax::UnimplementedError
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'identifies InternalError' do
|
176
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(13, 'internal')
|
177
|
+
expect(mapped_error).to eq Google::Gax::InternalError
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'identifies UnavailableError' do
|
181
|
+
mapped_error =
|
182
|
+
Google::Gax.from_error GRPC::BadStatus.new(14, 'unavailable')
|
183
|
+
expect(mapped_error).to eq Google::Gax::UnavailableError
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'identifies DataLossError' do
|
187
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(15, 'data loss')
|
188
|
+
expect(mapped_error).to eq Google::Gax::DataLossError
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'identifies UnauthenticatedError' do
|
192
|
+
mapped_error =
|
193
|
+
Google::Gax.from_error GRPC::BadStatus.new(16, 'unauthenticated')
|
194
|
+
expect(mapped_error).to eq Google::Gax::UnauthenticatedError
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'identifies unknown error' do
|
198
|
+
# We don't know what to map this error case to
|
199
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(0, 'unknown')
|
200
|
+
expect(mapped_error).to eq Google::Gax::GaxError
|
201
|
+
|
202
|
+
mapped_error = Google::Gax.from_error GRPC::BadStatus.new(17, 'unknown')
|
203
|
+
expect(mapped_error).to eq Google::Gax::GaxError
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
111
207
|
def wrap_with_gax_error(err)
|
112
208
|
raise err
|
113
209
|
rescue => e
|
114
|
-
|
210
|
+
klass = Google::Gax.from_error(e)
|
211
|
+
raise klass.new(e.message)
|
115
212
|
end
|
116
213
|
|
117
214
|
def wrapped_error(msg)
|
@@ -29,7 +29,9 @@
|
|
29
29
|
|
30
30
|
require 'google/gax'
|
31
31
|
require 'google/protobuf/any_pb'
|
32
|
+
require 'google/protobuf/timestamp_pb'
|
32
33
|
require 'spec/fixtures/fixture_pb'
|
34
|
+
require 'stringio'
|
33
35
|
|
34
36
|
describe Google::Gax do
|
35
37
|
describe '#to_proto' do
|
@@ -110,6 +112,38 @@ describe Google::Gax do
|
|
110
112
|
end
|
111
113
|
end
|
112
114
|
|
115
|
+
it 'handles IO instances' do
|
116
|
+
file = File.new('spec/fixtures/fixture_file.txt')
|
117
|
+
request_hash = {
|
118
|
+
bytes_field: file
|
119
|
+
}
|
120
|
+
user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
|
121
|
+
expect(user.bytes_field).to eq("This is a text file.\n")
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'handles StringIO instances' do
|
125
|
+
expected = 'This is a StringIO.'
|
126
|
+
string_io = StringIO.new(expected)
|
127
|
+
request_hash = {
|
128
|
+
bytes_field: string_io
|
129
|
+
}
|
130
|
+
user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
|
131
|
+
expect(user.bytes_field).to eq(expected)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'auto-coerces Time' do
|
135
|
+
seconds = 271_828_182
|
136
|
+
nanos = 845_904_523
|
137
|
+
# Fixnum, not float, for precision
|
138
|
+
sometime = seconds + nanos * 10**-9
|
139
|
+
request_hash = {
|
140
|
+
timestamp: Time.at(sometime)
|
141
|
+
}
|
142
|
+
user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
|
143
|
+
expected = Google::Protobuf::Timestamp.new(seconds: seconds, nanos: nanos)
|
144
|
+
expect(user.timestamp).to eq(expected)
|
145
|
+
end
|
146
|
+
|
113
147
|
it 'fails if a key does not exist in the target message type' do
|
114
148
|
user_hash = {
|
115
149
|
name: USER_NAME,
|
@@ -135,4 +169,31 @@ describe Google::Gax do
|
|
135
169
|
end.to raise_error(ArgumentError)
|
136
170
|
end
|
137
171
|
end
|
172
|
+
|
173
|
+
describe 'time-timestamp conversion' do
|
174
|
+
SECONDS = 271_828_182
|
175
|
+
NANOS = 845_904_523
|
176
|
+
A_TIME = Time.at(SECONDS + NANOS * 10**-9)
|
177
|
+
A_TIMESTAMP =
|
178
|
+
Google::Protobuf::Timestamp.new(seconds: SECONDS, nanos: NANOS)
|
179
|
+
|
180
|
+
it 'converts time to timestamp' do
|
181
|
+
expect(Google::Gax.time_to_timestamp(A_TIME)).to eq A_TIMESTAMP
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'converts timestamp to time' do
|
185
|
+
expect(Google::Gax.timestamp_to_time(A_TIMESTAMP)).to eq A_TIME
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'is an identity when conversion is a round trip' do
|
189
|
+
expect(
|
190
|
+
Google::Gax.timestamp_to_time(Google::Gax.time_to_timestamp(A_TIME))
|
191
|
+
).to eq A_TIME
|
192
|
+
expect(
|
193
|
+
Google::Gax.time_to_timestamp(
|
194
|
+
Google::Gax.timestamp_to_time(A_TIMESTAMP)
|
195
|
+
)
|
196
|
+
).to eq A_TIMESTAMP
|
197
|
+
end
|
198
|
+
end
|
138
199
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-gax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Google API Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: googleauth
|
@@ -184,6 +184,7 @@ files:
|
|
184
184
|
- lib/google/longrunning/operations_client.rb
|
185
185
|
- lib/google/longrunning/operations_client_config.json
|
186
186
|
- spec/fixtures/fixture.proto
|
187
|
+
- spec/fixtures/fixture_file.txt
|
187
188
|
- spec/fixtures/fixture_pb.rb
|
188
189
|
- spec/google/gax/api_callable_spec.rb
|
189
190
|
- spec/google/gax/bundling_spec.rb
|
@@ -214,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
215
|
version: '0'
|
215
216
|
requirements: []
|
216
217
|
rubyforge_project:
|
217
|
-
rubygems_version: 2.
|
218
|
+
rubygems_version: 2.6.12
|
218
219
|
signing_key:
|
219
220
|
specification_version: 4
|
220
221
|
summary: Aids the development of APIs for clients and servers based on GRPC and Google
|