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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4796002440be1be16d777561582938e9ba8651636a7ebdc14e5f2ec5500e317
4
- data.tar.gz: 47658a764095cc220dc087f9c12199cbfd78490c32f25949f4c93d94790525bc
3
+ metadata.gz: dc699a3d9a47acc1b8bdb7196b0da1280847caa14d5405e0150e8608cd701501
4
+ data.tar.gz: 3884004454f86b2a7cd7c1ad460c00f6c820edae6b0bccc7a87d177a0cccee72
5
5
  SHA512:
6
- metadata.gz: e2ec6aff5358f4385d8d99db9ddcdfb2bf0987a50fbf2eefa12baebbbbebeeb6c206244fc57f7d73676be899e2d373975111f325cc147603b9b73ba3d0767a74
7
- data.tar.gz: d1b3823eb2ce13f7c2ed01e8cccefb36bb7a17500f25b260ffa7227e0bb0d3c77c06cf05f5ae7b6e0e963ab408d9ba398200da3f6bec0d3e23fb3647dd4977d1
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`����
@@ -169,6 +169,3 @@ Async do
169
169
  server.run
170
170
  end
171
171
  ```
172
-
173
-
174
-
data/design.md CHANGED
@@ -318,13 +318,18 @@ module Async
318
318
  end
319
319
  end
320
320
 
321
- # Check gRPC status and raise error if not OK
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
- if status != Protocol::GRPC::Status::OK
325
- message = Protocol::GRPC::Metadata.extract_message(response.headers)
326
- raise Protocol::GRPC::Error.new(status, message)
327
- end
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
- - Basic error handling and status checking
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
 
@@ -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
- readable_body = Protocol::GRPC::Body::ReadableBody.new(
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
- message = readable_body.read
176
- readable_body.close
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
- message
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
- readable_body = Protocol::GRPC::Body::ReadableBody.new(
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
- begin
222
- readable_body.each(&block)
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
- readable_body
231
- rescue StandardError
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
- raise Protocol::GRPC::Error.for(status, message, metadata: metadata)
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[:method]
70
- request_class = rpc_descriptor[:request_class]
71
- response_class = rpc_descriptor[:response_class]
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 call context:
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
- timeout_value = request.headers["grpc-timeout"]
90
- deadline = if timeout_value
91
- timeout_seconds = Protocol::GRPC::Methods.parse_timeout(timeout_value)
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 = Protocol::GRPC::Call.new(request, deadline: deadline)
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
- # Close output stream:
102
- output.close_write unless output.closed?
103
-
104
- # Mark trailers and add status:
105
- response_headers.trailer!
106
- Protocol::GRPC::Metadata.add_status_trailer!(response_headers, status: Protocol::GRPC::Status::OK)
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
- Protocol::HTTP::Response[200, response_headers, output]
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
@@ -58,36 +58,12 @@ module Async
58
58
  descriptions = {}
59
59
 
60
60
  @interface_class.rpcs.each do |pascal_case_name, rpc|
61
- # Use explicit method name if provided, otherwise convert PascalCase to snake_case:
62
- ruby_method_name = if rpc.method
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
@@ -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 and PascalCase name for path building
28
- @rpcs_by_method[snake_case_method] = [rpc, pascal_case_name]
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, pascal_case_name = @rpcs_by_method[method_name]
82
- return [rpc, pascal_case_name]
80
+ rpc = @rpcs_by_method[method_name]
81
+ return [rpc, rpc.name]
83
82
  end
84
83
 
85
84
  [nil, nil]
@@ -7,6 +7,7 @@
7
7
  module Async
8
8
  # @namespace
9
9
  module GRPC
10
- VERSION = "0.1.0"
10
+ VERSION = "0.2.0"
11
11
  end
12
12
  end
13
+
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
- - **Interface-based services** - Define services using `Protocol::GRPC::Interface` with automatic PascalCase to snake\_case method name conversion for Ruby implementations.
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.1.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.2'
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.2'
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