async-grpc 0.1.0 → 0.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
- checksums.yaml.gz.sig +3 -0
- data/context/getting-started.md +0 -3
- data/design.md +11 -6
- data/lib/async/grpc/client.rb +18 -38
- data/lib/async/grpc/dispatcher_middleware.rb +56 -21
- data/lib/async/grpc/remote_error.rb +19 -0
- data/lib/async/grpc/service.rb +2 -26
- data/lib/async/grpc/stub.rb +5 -6
- data/lib/async/grpc/version.rb +2 -1
- data/readme.md +10 -2
- data/releases.md +9 -0
- data.tar.gz.sig +0 -0
- metadata +34 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dc699a3d9a47acc1b8bdb7196b0da1280847caa14d5405e0150e8608cd701501
|
|
4
|
+
data.tar.gz: 3884004454f86b2a7cd7c1ad460c00f6c820edae6b0bccc7a87d177a0cccee72
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d487819bdab689d575b8985e84b81d1ad1293126f9a7f64d697853cf723a4cdf67bb607f0e20faa0f1e547baf0eea6d9dc102da576b450bcba5e42f72ad2e95
|
|
7
|
+
data.tar.gz: 9f2bf511ff8fc16db342add52bedbfbf1c924c6109346e9d3e877abb2e2ff6f03f40c50ef9a46406df2895b22b6a32845a22a7d444617ed65bc11ab4ee82ae52
|
checksums.yaml.gz.sig
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
���Zژ��X�7X�tE����Q�-�w��3J^��Db�������]9��_�F�
|
|
2
|
+
#��?a���#;�8ʗ(xB�������P��"�q.����ȺOy�|M]l����v [x�I��Y92�%�H�+n���'�� ~zJ@%q�;�8�س��L<Y��3
|
|
3
|
+
vJ�s�ڿ'��a���#m�5���w�&A[�]� �s�(?�M��+���SG烰G!�<�A�4�+8j����5��7Q�;j��A���μ/Bva%L���%7(BKN�d���˪���y���Z�ALrXRሼ�����'<�[�ve4�J]�MsM���TO�q ���X<���I������ʪ�i}�n�Pkw��y���Y�~P`����
|
data/context/getting-started.md
CHANGED
data/design.md
CHANGED
|
@@ -318,13 +318,18 @@ module Async
|
|
|
318
318
|
end
|
|
319
319
|
end
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
# Check gRPC status and raise error if not OK
|
|
322
322
|
def check_status!(response)
|
|
323
323
|
status = Protocol::GRPC::Metadata.extract_status(response.headers)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
324
|
+
|
|
325
|
+
return if status == Protocol::GRPC::Status::OK
|
|
326
|
+
|
|
327
|
+
message = Protocol::GRPC::Metadata.extract_message(response.headers)
|
|
328
|
+
metadata = Protocol::GRPC::Methods.extract_metadata(response.headers)
|
|
329
|
+
|
|
330
|
+
remote_error = RemoteError.for(message, metadata)
|
|
331
|
+
|
|
332
|
+
raise Protocol::GRPC::Error.for(status, metadata: metadata), cause: remote_error
|
|
328
333
|
end
|
|
329
334
|
end
|
|
330
335
|
end
|
|
@@ -1001,7 +1006,7 @@ This enables async-grpc to be used as a drop-in replacement for the standard `gr
|
|
|
1001
1006
|
### Phase 1: Core Client (✅ Designed)
|
|
1002
1007
|
- `Async::GRPC::Client` with all four RPC types
|
|
1003
1008
|
- `Async::GRPC::ServerCall` context object (enhances Protocol::GRPC::Call)
|
|
1004
|
-
-
|
|
1009
|
+
- Error handling with backtrace support via `RemoteError` and exception chaining
|
|
1005
1010
|
- Response body wrapping pattern
|
|
1006
1011
|
- **Server**: Just use `Protocol::GRPC::Middleware` with `Async::HTTP::Server` (no wrapper needed!)
|
|
1007
1012
|
|
data/lib/async/grpc/client.rb
CHANGED
|
@@ -16,6 +16,7 @@ require "protocol/grpc/body/writable_body"
|
|
|
16
16
|
require "protocol/grpc/metadata"
|
|
17
17
|
require "protocol/grpc/error"
|
|
18
18
|
require_relative "stub"
|
|
19
|
+
require_relative "remote_error"
|
|
19
20
|
|
|
20
21
|
module Async
|
|
21
22
|
module GRPC
|
|
@@ -100,7 +101,9 @@ module Async
|
|
|
100
101
|
def call(request)
|
|
101
102
|
request.headers = @headers.merge(request.headers)
|
|
102
103
|
|
|
103
|
-
super
|
|
104
|
+
super.tap do |response|
|
|
105
|
+
response.headers.policy = Protocol::GRPC::HEADER_POLICY
|
|
106
|
+
end
|
|
104
107
|
end
|
|
105
108
|
|
|
106
109
|
# Make a gRPC call.
|
|
@@ -166,19 +169,17 @@ module Async
|
|
|
166
169
|
begin
|
|
167
170
|
# Read body first - trailers are only available after body is consumed
|
|
168
171
|
response_encoding = response.headers["grpc-encoding"]
|
|
169
|
-
|
|
170
|
-
response.body,
|
|
171
|
-
message_class: response_class,
|
|
172
|
-
encoding: response_encoding
|
|
173
|
-
)
|
|
172
|
+
response_body = Protocol::GRPC::Body::ReadableBody.wrap(response, message_class: response_class, encoding: response_encoding)
|
|
174
173
|
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
if response_body
|
|
175
|
+
response_value = response_body.read
|
|
176
|
+
response_body.close
|
|
177
|
+
end
|
|
177
178
|
|
|
178
179
|
# Check status after reading body (trailers are now available)
|
|
179
180
|
check_status!(response)
|
|
180
181
|
|
|
181
|
-
|
|
182
|
+
return response_value
|
|
182
183
|
ensure
|
|
183
184
|
response.close
|
|
184
185
|
end
|
|
@@ -203,32 +204,19 @@ module Async
|
|
|
203
204
|
response = call(http_request)
|
|
204
205
|
|
|
205
206
|
begin
|
|
206
|
-
# Set gRPC policy BEFORE reading body so trailers are processed correctly:
|
|
207
|
-
unless response.headers.policy == Protocol::GRPC::HEADER_POLICY
|
|
208
|
-
response.headers.policy = Protocol::GRPC::HEADER_POLICY
|
|
209
|
-
end
|
|
210
|
-
|
|
211
207
|
# Read body first - trailers are only available after body is consumed:
|
|
212
208
|
response_encoding = response.headers["grpc-encoding"]
|
|
213
|
-
|
|
214
|
-
response.body,
|
|
215
|
-
message_class: response_class,
|
|
216
|
-
encoding: response_encoding
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
return readable_body unless block_given?
|
|
209
|
+
response_body = Protocol::GRPC::Body::ReadableBody.wrap(response, message_class: response_class, encoding: response_encoding)
|
|
220
210
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
ensure
|
|
224
|
-
readable_body.close
|
|
211
|
+
if block_given? and response_body
|
|
212
|
+
response_body.each(&block)
|
|
225
213
|
end
|
|
226
214
|
|
|
227
215
|
# Check status after reading all body chunks (trailers are now available):
|
|
228
216
|
check_status!(response)
|
|
229
217
|
|
|
230
|
-
|
|
231
|
-
rescue
|
|
218
|
+
return response_body
|
|
219
|
+
rescue
|
|
232
220
|
response.close
|
|
233
221
|
raise
|
|
234
222
|
end
|
|
@@ -327,24 +315,16 @@ module Async
|
|
|
327
315
|
# @parameter response [Protocol::HTTP::Response]
|
|
328
316
|
# @raises [Protocol::GRPC::Error] If status is not OK
|
|
329
317
|
def check_status!(response)
|
|
330
|
-
# Policy should already be set before calling this method:
|
|
331
|
-
# But ensure it's set just in case
|
|
332
|
-
unless response.headers.policy == Protocol::GRPC::HEADER_POLICY
|
|
333
|
-
response.headers.policy = Protocol::GRPC::HEADER_POLICY
|
|
334
|
-
end
|
|
335
|
-
|
|
336
318
|
status = Protocol::GRPC::Metadata.extract_status(response.headers)
|
|
337
319
|
|
|
338
|
-
# If status is UNKNOWN (not found), default to OK:
|
|
339
|
-
# This handles cases where trailers aren't available or status wasn't set
|
|
340
|
-
status = Protocol::GRPC::Status::OK if status == Protocol::GRPC::Status::UNKNOWN
|
|
341
|
-
|
|
342
320
|
return if status == Protocol::GRPC::Status::OK
|
|
343
321
|
|
|
344
322
|
message = Protocol::GRPC::Metadata.extract_message(response.headers)
|
|
345
323
|
metadata = Protocol::GRPC::Methods.extract_metadata(response.headers)
|
|
346
324
|
|
|
347
|
-
|
|
325
|
+
remote_error = RemoteError.for(message, metadata)
|
|
326
|
+
|
|
327
|
+
raise Protocol::GRPC::Error.for(status, metadata: metadata), cause: remote_error
|
|
348
328
|
end
|
|
349
329
|
end
|
|
350
330
|
end
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2025, by Samuel Williams.
|
|
5
5
|
|
|
6
|
+
require "async"
|
|
7
|
+
require "async/deadline"
|
|
8
|
+
|
|
6
9
|
require "protocol/grpc/middleware"
|
|
7
10
|
require "protocol/grpc/methods"
|
|
8
11
|
require "protocol/grpc/call"
|
|
@@ -41,6 +44,38 @@ module Async
|
|
|
41
44
|
|
|
42
45
|
protected
|
|
43
46
|
|
|
47
|
+
def invoke_service(service, handler_method, input, output, call)
|
|
48
|
+
begin
|
|
49
|
+
service.send(handler_method, input, output, call)
|
|
50
|
+
ensure
|
|
51
|
+
# Close input stream:
|
|
52
|
+
input.close
|
|
53
|
+
|
|
54
|
+
# Close output stream:
|
|
55
|
+
output.close_write unless output.closed?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Mark trailers and add status (if not already set by handler):
|
|
59
|
+
if call.response&.headers
|
|
60
|
+
call.response.headers.trailer!
|
|
61
|
+
|
|
62
|
+
# Only add OK status if grpc-status hasn't been set by the handler:
|
|
63
|
+
unless call.response.headers["grpc-status"]
|
|
64
|
+
Protocol::GRPC::Metadata.add_status!(call.response.headers, status: Protocol::GRPC::Status::OK)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def dispatch_to_service(service, handler_method, input, output, call, deadline, parent: Async::Task.current)
|
|
70
|
+
if deadline
|
|
71
|
+
parent.with_timeout(deadline) do
|
|
72
|
+
invoke_service(service, handler_method, input, output, call)
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
invoke_service(service, handler_method, input, output, call)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
44
79
|
# Dispatch the request to the appropriate service.
|
|
45
80
|
# @parameter request [Protocol::HTTP::Request] The HTTP request
|
|
46
81
|
# @returns [Protocol::HTTP::Response] The HTTP response
|
|
@@ -66,9 +101,9 @@ module Async
|
|
|
66
101
|
raise Protocol::GRPC::Error.new(Protocol::GRPC::Status::UNIMPLEMENTED, "Method not found: #{method_name}")
|
|
67
102
|
end
|
|
68
103
|
|
|
69
|
-
handler_method = rpc_descriptor
|
|
70
|
-
request_class = rpc_descriptor
|
|
71
|
-
response_class = rpc_descriptor
|
|
104
|
+
handler_method = rpc_descriptor.method
|
|
105
|
+
request_class = rpc_descriptor.request_class
|
|
106
|
+
response_class = rpc_descriptor.response_class
|
|
72
107
|
|
|
73
108
|
# Verify handler method exists:
|
|
74
109
|
unless service.respond_to?(handler_method, true)
|
|
@@ -80,34 +115,34 @@ module Async
|
|
|
80
115
|
input = Protocol::GRPC::Body::ReadableBody.new(request.body, message_class: request_class, encoding: encoding)
|
|
81
116
|
output = Protocol::GRPC::Body::WritableBody.new(message_class: response_class, encoding: encoding)
|
|
82
117
|
|
|
83
|
-
# Create
|
|
118
|
+
# Create response headers:
|
|
84
119
|
response_headers = Protocol::HTTP::Headers.new([], nil, policy: Protocol::GRPC::HEADER_POLICY)
|
|
85
120
|
response_headers["content-type"] = "application/grpc+proto"
|
|
86
121
|
response_headers["grpc-encoding"] = encoding if encoding
|
|
87
122
|
|
|
123
|
+
# Create response object:
|
|
124
|
+
response = Protocol::HTTP::Response[200, response_headers, output]
|
|
125
|
+
|
|
88
126
|
# Parse deadline from timeout header:
|
|
89
|
-
|
|
90
|
-
deadline = if
|
|
91
|
-
|
|
92
|
-
require "async/deadline"
|
|
93
|
-
Async::Deadline.start(timeout_seconds) if timeout_seconds
|
|
127
|
+
timeout = Protocol::GRPC::Methods.parse_timeout(request.headers["grpc-timeout"])
|
|
128
|
+
deadline = if timeout
|
|
129
|
+
Async::Deadline.start(timeout)
|
|
94
130
|
end
|
|
95
131
|
|
|
96
|
-
call
|
|
97
|
-
|
|
98
|
-
# Call the handler method on the service:
|
|
99
|
-
service.send(handler_method, input, output, call)
|
|
132
|
+
# Create call context with request and response:
|
|
133
|
+
call = Protocol::GRPC::Call.new(request, response, deadline: deadline)
|
|
100
134
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
135
|
+
if rpc_descriptor.streaming?
|
|
136
|
+
Async do |task|
|
|
137
|
+
dispatch_to_service(service, handler_method, input, output, call, deadline, parent: task)
|
|
138
|
+
end
|
|
139
|
+
else
|
|
140
|
+
# Unary call:
|
|
141
|
+
dispatch_to_service(service, handler_method, input, output, call, deadline)
|
|
142
|
+
end
|
|
107
143
|
|
|
108
|
-
|
|
144
|
+
response
|
|
109
145
|
end
|
|
110
146
|
end
|
|
111
147
|
end
|
|
112
148
|
end
|
|
113
|
-
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
module Async
|
|
7
|
+
module GRPC
|
|
8
|
+
class RemoteError < StandardError
|
|
9
|
+
def self.for(message, metadata)
|
|
10
|
+
self.new(message).tap do |error|
|
|
11
|
+
if backtrace = metadata.delete("backtrace")
|
|
12
|
+
# Backtrace is always an array (Split header format):
|
|
13
|
+
error.set_backtrace(backtrace)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/async/grpc/service.rb
CHANGED
|
@@ -58,36 +58,12 @@ module Async
|
|
|
58
58
|
descriptions = {}
|
|
59
59
|
|
|
60
60
|
@interface_class.rpcs.each do |pascal_case_name, rpc|
|
|
61
|
-
#
|
|
62
|
-
|
|
63
|
-
rpc.method
|
|
64
|
-
else
|
|
65
|
-
snake_case_name = pascal_case_to_snake_case(pascal_case_name.to_s)
|
|
66
|
-
snake_case_name.to_sym
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
descriptions[pascal_case_name.to_s] = {
|
|
70
|
-
method: ruby_method_name,
|
|
71
|
-
request_class: rpc.request_class,
|
|
72
|
-
response_class: rpc.response_class,
|
|
73
|
-
streaming: rpc.streaming
|
|
74
|
-
}
|
|
61
|
+
# rpc.method is always set (either explicitly or auto-converted in Interface.rpc)
|
|
62
|
+
descriptions[pascal_case_name.to_s] = rpc
|
|
75
63
|
end
|
|
76
64
|
|
|
77
65
|
descriptions
|
|
78
66
|
end
|
|
79
|
-
|
|
80
|
-
private
|
|
81
|
-
|
|
82
|
-
# Convert PascalCase to snake_case.
|
|
83
|
-
# @parameter pascal_case [String] PascalCase string (e.g., "SayHello")
|
|
84
|
-
# @returns [String] snake_case string (e.g., "say_hello")
|
|
85
|
-
def pascal_case_to_snake_case(pascal_case)
|
|
86
|
-
pascal_case
|
|
87
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # Insert underscore before capital letters followed by lowercase
|
|
88
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2') # Insert underscore between lowercase/digit and uppercase
|
|
89
|
-
.downcase
|
|
90
|
-
end
|
|
91
67
|
end
|
|
92
68
|
end
|
|
93
69
|
end
|
data/lib/async/grpc/stub.rb
CHANGED
|
@@ -24,8 +24,8 @@ module Async
|
|
|
24
24
|
# rpc.method is always set (either explicit or auto-converted from PascalCase)
|
|
25
25
|
snake_case_method = rpc.method
|
|
26
26
|
|
|
27
|
-
# Index by snake_case method name, storing RPC
|
|
28
|
-
@rpcs_by_method[snake_case_method] =
|
|
27
|
+
# Index by snake_case method name, storing RPC (which includes name field)
|
|
28
|
+
@rpcs_by_method[snake_case_method] = rpc
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -53,8 +53,7 @@ module Async
|
|
|
53
53
|
encoding = options.delete(:encoding)
|
|
54
54
|
|
|
55
55
|
# Delegate to client.invoke with PascalCase method name (for interface lookup):
|
|
56
|
-
@client.invoke(@interface, interface_method_name, request, metadata: metadata, timeout: timeout, encoding: encoding,
|
|
57
|
-
&block)
|
|
56
|
+
@client.invoke(@interface, interface_method_name, request, metadata: metadata, timeout: timeout, encoding: encoding, &block)
|
|
58
57
|
else
|
|
59
58
|
super
|
|
60
59
|
end
|
|
@@ -78,8 +77,8 @@ module Async
|
|
|
78
77
|
# @returns [Array(Protocol::GRPC::RPC, Symbol) | Array(Nil, Nil)] RPC definition and PascalCase method name, or nil if not found
|
|
79
78
|
def lookup_rpc(method_name)
|
|
80
79
|
if @rpcs_by_method.key?(method_name)
|
|
81
|
-
rpc
|
|
82
|
-
return [rpc,
|
|
80
|
+
rpc = @rpcs_by_method[method_name]
|
|
81
|
+
return [rpc, rpc.name]
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
[nil, nil]
|
data/lib/async/grpc/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -12,8 +12,7 @@ Asynchronous gRPC client and server implementation built on top of `protocol-grp
|
|
|
12
12
|
- **Method-based stubs** - Create type-safe stubs from `Protocol::GRPC::Interface` definitions. Accepts both PascalCase and snake\_case method names for convenience.
|
|
13
13
|
- **Server middleware** - `DispatcherMiddleware` routes requests to registered services based on path.
|
|
14
14
|
- **All RPC patterns** - Supports unary, server streaming, client streaming, and bidirectional streaming RPCs.
|
|
15
|
-
- **
|
|
16
|
-
- **HTTP/2 transport** - Built on `async-http` with automatic HTTP/2 multiplexing and connection pooling.
|
|
15
|
+
- **HTTP/1 and HTTP/2 transport** - Built on `async-http` with automatic HTTP/2 multiplexing and connection pooling.
|
|
17
16
|
|
|
18
17
|
## Usage
|
|
19
18
|
|
|
@@ -25,8 +24,17 @@ Please see the [project documentation](https://socketry.github.io/async-grpc/) f
|
|
|
25
24
|
|
|
26
25
|
Please see the [project releases](https://socketry.github.io/async-grpc/releases/index) for all releases.
|
|
27
26
|
|
|
27
|
+
### v0.2.0
|
|
28
|
+
|
|
29
|
+
- Added `Async::GRPC::RemoteError` class to encapsulate remote error details including message and backtrace extracted from response headers.
|
|
30
|
+
- Client-side error handling now extracts backtraces from response metadata and sets them on `RemoteError`, which is chained as the `cause` of `Protocol::GRPC::Error` for better debugging.
|
|
31
|
+
- Updated to use `Protocol::GRPC::Metadata.add_status!` instead of deprecated `add_status_trailer!` method.
|
|
32
|
+
- Tidy up request and response body handling.
|
|
33
|
+
|
|
28
34
|
### v0.1.0
|
|
29
35
|
|
|
36
|
+
- Initial hack.
|
|
37
|
+
|
|
30
38
|
## See Also
|
|
31
39
|
|
|
32
40
|
- [protocol-grpc](https://github.com/socketry/protocol-grpc) — Protocol abstractions for gRPC that this gem builds upon.
|
data/releases.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.2.0
|
|
4
|
+
|
|
5
|
+
- Added `Async::GRPC::RemoteError` class to encapsulate remote error details including message and backtrace extracted from response headers.
|
|
6
|
+
- Client-side error handling now extracts backtraces from response metadata and sets them on `RemoteError`, which is chained as the `cause` of `Protocol::GRPC::Error` for better debugging.
|
|
7
|
+
- Updated to use `Protocol::GRPC::Metadata.add_status!` instead of deprecated `add_status_trailer!` method.
|
|
8
|
+
- Tidy up request and response body handling.
|
|
9
|
+
|
|
3
10
|
## v0.1.0
|
|
11
|
+
|
|
12
|
+
- Initial hack.
|
data.tar.gz.sig
ADDED
|
Binary file
|
metadata
CHANGED
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: async-grpc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
8
8
|
bindir: bin
|
|
9
|
-
cert_chain:
|
|
9
|
+
cert_chain:
|
|
10
|
+
- |
|
|
11
|
+
-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
|
|
13
|
+
ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
|
|
14
|
+
CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
|
|
15
|
+
MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
|
|
16
|
+
MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
|
|
17
|
+
bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
|
|
18
|
+
igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
|
|
19
|
+
9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
|
|
20
|
+
sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
|
|
21
|
+
e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
|
|
22
|
+
XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
|
|
23
|
+
RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
|
|
24
|
+
tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
|
|
25
|
+
zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
|
|
26
|
+
xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
|
27
|
+
BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
|
|
28
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
|
|
29
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
|
|
30
|
+
cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
|
|
31
|
+
xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
|
|
32
|
+
c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
|
|
33
|
+
8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
|
|
34
|
+
JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
|
|
35
|
+
eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
|
|
36
|
+
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
|
37
|
+
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
|
38
|
+
-----END CERTIFICATE-----
|
|
10
39
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
40
|
dependencies:
|
|
12
41
|
- !ruby/object:Gem::Dependency
|
|
@@ -29,14 +58,14 @@ dependencies:
|
|
|
29
58
|
requirements:
|
|
30
59
|
- - "~>"
|
|
31
60
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0.
|
|
61
|
+
version: '0.5'
|
|
33
62
|
type: :runtime
|
|
34
63
|
prerelease: false
|
|
35
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
65
|
requirements:
|
|
37
66
|
- - "~>"
|
|
38
67
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
68
|
+
version: '0.5'
|
|
40
69
|
executables: []
|
|
41
70
|
extensions: []
|
|
42
71
|
extra_rdoc_files: []
|
|
@@ -48,6 +77,7 @@ files:
|
|
|
48
77
|
- lib/async/grpc.rb
|
|
49
78
|
- lib/async/grpc/client.rb
|
|
50
79
|
- lib/async/grpc/dispatcher_middleware.rb
|
|
80
|
+
- lib/async/grpc/remote_error.rb
|
|
51
81
|
- lib/async/grpc/service.rb
|
|
52
82
|
- lib/async/grpc/stub.rb
|
|
53
83
|
- lib/async/grpc/version.rb
|
metadata.gz.sig
ADDED
|
Binary file
|