grpc_kit 0.1.3 → 0.1.4
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/.travis.yml +0 -1
- data/TODO.md +1 -1
- data/examples/helloworld_client.rb +5 -1
- data/examples/routeguide_client.rb +5 -2
- data/lib/grpc_kit/calls/client_client_streamer.rb +29 -0
- data/lib/grpc_kit/calls/client_request_response.rb +25 -0
- data/lib/grpc_kit/calls/client_server_streamer.rb +29 -0
- data/lib/grpc_kit/calls/server_client_streamer.rb +32 -0
- data/lib/grpc_kit/calls/server_request_response.rb +32 -0
- data/lib/grpc_kit/calls/server_server_streamer.rb +32 -0
- data/lib/grpc_kit/calls.rb +39 -0
- data/lib/grpc_kit/client.rb +17 -17
- data/lib/grpc_kit/grpc_time.rb +100 -0
- data/lib/grpc_kit/interceptors/client_client_streamer.rb +19 -0
- data/lib/grpc_kit/interceptors/client_request_response.rb +39 -0
- data/lib/grpc_kit/interceptors/client_server_streamer.rb +19 -0
- data/lib/grpc_kit/interceptors/server_client_streamer.rb +15 -0
- data/lib/grpc_kit/interceptors/server_request_response.rb +36 -0
- data/lib/grpc_kit/interceptors/server_server_streamer.rb +17 -0
- data/lib/grpc_kit/interceptors.rb +64 -5
- data/lib/grpc_kit/rpc_desc.rb +18 -2
- data/lib/grpc_kit/rpcs/client_bidi_streamer.rb +11 -0
- data/lib/grpc_kit/rpcs/client_client_streamer.rb +23 -0
- data/lib/grpc_kit/rpcs/client_request_response.rb +31 -0
- data/lib/grpc_kit/rpcs/client_server_streamer.rb +19 -0
- data/lib/grpc_kit/rpcs/server_bidi_streamer.rb +10 -0
- data/lib/grpc_kit/rpcs/server_client_streamer.rb +24 -0
- data/lib/grpc_kit/rpcs/server_request_response.rb +26 -0
- data/lib/grpc_kit/rpcs/server_server_streamer.rb +26 -0
- data/lib/grpc_kit/rpcs.rb +21 -5
- data/lib/grpc_kit/server.rb +16 -7
- data/lib/grpc_kit/session/headers.rb +2 -2
- data/lib/grpc_kit/session/stream.rb +5 -0
- data/lib/grpc_kit/{session/client.rb → sessions/client_session.rb} +5 -6
- data/lib/grpc_kit/{session/server.rb → sessions/server_session.rb} +21 -8
- data/lib/grpc_kit/streams/client_stream.rb +146 -0
- data/lib/grpc_kit/streams/server_stream.rb +105 -0
- data/lib/grpc_kit/{streams → transport}/packable.rb +2 -2
- data/lib/grpc_kit/{streams → transport}/send_buffer.rb +1 -1
- data/lib/grpc_kit/transports/client_transport.rb +96 -0
- data/lib/grpc_kit/transports/server_transport.rb +68 -0
- data/lib/grpc_kit/version.rb +1 -1
- metadata +32 -21
- data/lib/grpc_kit/interceptors/client_streamer.rb +0 -31
- data/lib/grpc_kit/interceptors/request_response.rb +0 -70
- data/lib/grpc_kit/interceptors/server_streamer.rb +0 -33
- data/lib/grpc_kit/interceptors/streaming.rb +0 -70
- data/lib/grpc_kit/rpcs/base.rb +0 -30
- data/lib/grpc_kit/rpcs/bidi_streamer.rb +0 -18
- data/lib/grpc_kit/rpcs/call.rb +0 -27
- data/lib/grpc_kit/rpcs/client_streamer.rb +0 -38
- data/lib/grpc_kit/rpcs/error.rb +0 -23
- data/lib/grpc_kit/rpcs/request_response.rb +0 -64
- data/lib/grpc_kit/rpcs/server_streamer.rb +0 -42
- data/lib/grpc_kit/session/duration.rb +0 -97
- data/lib/grpc_kit/stream.rb +0 -120
- data/lib/grpc_kit/streams/client.rb +0 -113
- data/lib/grpc_kit/streams/server.rb +0 -54
data/lib/grpc_kit/rpc_desc.rb
CHANGED
@@ -1,9 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'grpc_kit/method_config'
|
4
|
-
require 'grpc_kit/rpcs'
|
5
4
|
require 'grpc_kit/protobuffer'
|
6
|
-
|
5
|
+
|
6
|
+
require 'grpc_kit/interceptors/client_request_response'
|
7
|
+
require 'grpc_kit/interceptors/client_client_streamer'
|
8
|
+
require 'grpc_kit/interceptors/client_server_streamer'
|
9
|
+
# require 'grpc_kit/client_interceptors/bidi_streamer'
|
10
|
+
require 'grpc_kit/rpcs/client_request_response'
|
11
|
+
require 'grpc_kit/rpcs/client_client_streamer'
|
12
|
+
require 'grpc_kit/rpcs/client_server_streamer'
|
13
|
+
require 'grpc_kit/rpcs/client_bidi_streamer'
|
14
|
+
|
15
|
+
require 'grpc_kit/interceptors/server_request_response'
|
16
|
+
require 'grpc_kit/interceptors/server_client_streamer'
|
17
|
+
require 'grpc_kit/interceptors/server_server_streamer'
|
18
|
+
# require 'grpc_kit/server_interceptors/bidi_streamer'
|
19
|
+
require 'grpc_kit/rpcs/server_request_response'
|
20
|
+
require 'grpc_kit/rpcs/server_client_streamer'
|
21
|
+
require 'grpc_kit/rpcs/server_server_streamer'
|
22
|
+
require 'grpc_kit/rpcs/server_bidi_streamer'
|
7
23
|
|
8
24
|
module GrpcKit
|
9
25
|
class RpcDesc
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/client_client_streamer'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Client
|
8
|
+
class ClientStreamer < GrpcKit::Rpcs::ClientRpc
|
9
|
+
def invoke(stream, _request, metadata: {}, timeout: nil)
|
10
|
+
call = GrpcKit::Calls::Client::ClientStreamer.new(
|
11
|
+
metadata: metadata,
|
12
|
+
config: @config,
|
13
|
+
timeout: timeout,
|
14
|
+
stream: stream,
|
15
|
+
)
|
16
|
+
|
17
|
+
@config.interceptor.intercept(call, metadata) do |s|
|
18
|
+
s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/client_request_response'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Client
|
8
|
+
class RequestResponse < GrpcKit::Rpcs::ClientRpc
|
9
|
+
def invoke(stream, request, metadata: {}, timeout: nil)
|
10
|
+
call = GrpcKit::Calls::Client::RequestResponse.new(
|
11
|
+
metadata: metadata,
|
12
|
+
config: @config,
|
13
|
+
timeout: timeout,
|
14
|
+
stream: stream,
|
15
|
+
)
|
16
|
+
|
17
|
+
@config.interceptor.intercept(request, call, call.metadata) do |r, c, _|
|
18
|
+
if timeout
|
19
|
+
Timeout.timeout(timeout.to_f, GrpcKit::Errors::DeadlineExceeded) do
|
20
|
+
call.send_msg(r, timeout: timeout.to_s, metadata: c.metadata, last: true)
|
21
|
+
call.recv(last: true)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
call.send_msg(r, metadata: c.metadata, last: true)
|
25
|
+
call.recv(last: true)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/client_server_streamer'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Client
|
8
|
+
class ServerStreamer < GrpcKit::Rpcs::ClientRpc
|
9
|
+
def invoke(stream, request, metadata: {}, timeout: nil)
|
10
|
+
call = GrpcKit::Calls::Client::ServerStreamer.new(metadata: metadata, config: @config, timeout: timeout, stream: stream)
|
11
|
+
|
12
|
+
@config.interceptor.intercept(call, metadata) do |c, m|
|
13
|
+
c.send_msg(request, metadata: m, last: true)
|
14
|
+
c
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/server_client_streamer'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Server
|
8
|
+
class ClientStreamer < GrpcKit::Rpcs::ServerRpc
|
9
|
+
def invoke(stream, metadata: {})
|
10
|
+
call = GrpcKit::Calls::Server::ClientStreamer.new(metadata: metadata, config: @config, stream: stream)
|
11
|
+
|
12
|
+
if @config.interceptor
|
13
|
+
@config.interceptor.intercept(call) do |c|
|
14
|
+
resp = @handler.send(@config.ruby_style_method_name, c)
|
15
|
+
c.send_msg(resp, last: true)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
resp = @handler.send(@config.ruby_style_method_name, call)
|
19
|
+
call.send_msg(resp, last: true)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/server_request_response'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Server
|
8
|
+
class RequestResponse < GrpcKit::Rpcs::ServerRpc
|
9
|
+
def invoke(stream, metadata: {})
|
10
|
+
call = GrpcKit::Calls::Server::RequestResponse.new(metadata: metadata, config: @config, stream: stream)
|
11
|
+
request = call.recv(last: true)
|
12
|
+
|
13
|
+
resp =
|
14
|
+
if @config.interceptor
|
15
|
+
@config.interceptor.intercept(request, call) do |_, _|
|
16
|
+
@handler.send(@config.ruby_style_method_name, request, call)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
@handler.send(@config.ruby_style_method_name, request, call)
|
20
|
+
end
|
21
|
+
|
22
|
+
call.send_msg(resp, last: true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/rpcs'
|
4
|
+
require 'grpc_kit/calls/server_server_streamer'
|
5
|
+
|
6
|
+
module GrpcKit
|
7
|
+
module Rpcs::Server
|
8
|
+
class ServerStreamer < GrpcKit::Rpcs::ServerRpc
|
9
|
+
def invoke(stream, metadata: {})
|
10
|
+
call = GrpcKit::Calls::Server::ServerStreamer.new(metadata: metadata, config: @config, stream: stream)
|
11
|
+
|
12
|
+
if @config.interceptor
|
13
|
+
@config.interceptor.intercept(call) do |c|
|
14
|
+
request = c.recv(last: true)
|
15
|
+
@handler.send(@config.ruby_style_method_name, request, c)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
request = call.recv(last: true)
|
19
|
+
@handler.send(@config.ruby_style_method_name, request, call)
|
20
|
+
end
|
21
|
+
|
22
|
+
stream.send_status
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/grpc_kit/rpcs.rb
CHANGED
@@ -1,12 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'grpc_kit/
|
5
|
-
require 'grpc_kit/
|
6
|
-
require 'grpc_kit/rpcs/bidi_streamer'
|
7
|
-
require 'grpc_kit/rpcs/error'
|
3
|
+
require 'timeout'
|
4
|
+
require 'grpc_kit/errors'
|
5
|
+
require 'grpc_kit/status_codes'
|
8
6
|
|
9
7
|
module GrpcKit
|
10
8
|
module Rpcs
|
9
|
+
class ClientRpc
|
10
|
+
attr_reader :config
|
11
|
+
|
12
|
+
def initialize(config)
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke(stream, request, metadata: {}, timeout: nil); end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ServerRpc
|
20
|
+
def initialize(handler, config)
|
21
|
+
@handler = handler
|
22
|
+
@config = config
|
23
|
+
end
|
24
|
+
|
25
|
+
def invoke(stream, metadata: {}); end
|
26
|
+
end
|
11
27
|
end
|
12
28
|
end
|
data/lib/grpc_kit/server.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'grpc_kit/session/io'
|
4
|
-
require 'grpc_kit/
|
4
|
+
require 'grpc_kit/sessions/server_session'
|
5
5
|
|
6
6
|
module GrpcKit
|
7
7
|
class Server
|
8
8
|
def initialize(interceptors: [])
|
9
9
|
@sessions = []
|
10
10
|
@rpc_descs = {}
|
11
|
-
@error_rpc = GrpcKit::Rpcs::Server::Error.new
|
12
11
|
@interceptors = interceptors
|
13
12
|
@mutex = Mutex.new
|
14
13
|
|
@@ -41,19 +40,29 @@ module GrpcKit
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
|
-
def
|
45
|
-
|
43
|
+
def graceful_shutdown
|
44
|
+
@mutex.synchronize do
|
45
|
+
@sessions.each(&:drain)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @params path [String]
|
50
|
+
# @params stream [GrpcKit::Streams::ServerStream]
|
51
|
+
def dispatch(path, stream)
|
52
|
+
rpc = @rpc_descs[path]
|
46
53
|
unless rpc
|
47
|
-
|
54
|
+
e = GrpcKit::Errors::Unimplemented.new(path)
|
55
|
+
stream.send_status(status: e.code, msg: e.message)
|
56
|
+
return
|
48
57
|
end
|
49
58
|
|
50
|
-
|
59
|
+
stream.invoke(rpc)
|
51
60
|
end
|
52
61
|
|
53
62
|
private
|
54
63
|
|
55
64
|
def establish_session(conn)
|
56
|
-
session = GrpcKit::
|
65
|
+
session = GrpcKit::Sessions::ServerSession.new(GrpcKit::Session::IO.new(conn), self)
|
57
66
|
begin
|
58
67
|
@mutex.synchronize { @sessions << session }
|
59
68
|
yield(session)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'grpc_kit/
|
3
|
+
require 'grpc_kit/grpc_time'
|
4
4
|
|
5
5
|
module GrpcKit
|
6
6
|
module Session
|
@@ -45,7 +45,7 @@ module GrpcKit
|
|
45
45
|
when 'grpc-status'
|
46
46
|
self.grpc_status = val
|
47
47
|
when 'grpc-timeout'
|
48
|
-
self.timeout =
|
48
|
+
self.timeout = GrpcTime.new(val)
|
49
49
|
when 'grpc-message'
|
50
50
|
self.status_message = val
|
51
51
|
when 'grpc-status-details-bin'
|
@@ -1,27 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'forwardable'
|
4
3
|
require 'ds9'
|
4
|
+
require 'forwardable'
|
5
5
|
require 'grpc_kit/session/stream'
|
6
6
|
|
7
7
|
module GrpcKit
|
8
|
-
module
|
9
|
-
class
|
8
|
+
module Sessions
|
9
|
+
class ClientSession < DS9::Client
|
10
10
|
extend Forwardable
|
11
11
|
|
12
12
|
delegate %i[send_event recv_event] => :@io
|
13
13
|
|
14
14
|
# @params io [GrpcKit::Session::IO]
|
15
|
-
def initialize(io,
|
15
|
+
def initialize(io, opts = {})
|
16
16
|
super() # initialize DS9::Session
|
17
17
|
|
18
18
|
@io = io
|
19
19
|
@streams = {}
|
20
|
-
@handler = handler
|
21
20
|
@opts = opts
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
23
|
+
def send_request(data, headers)
|
25
24
|
stream_id = submit_request(headers, data)
|
26
25
|
stream = GrpcKit::Session::Stream.new(stream_id: stream_id, send_data: data)
|
27
26
|
stream.stream_id = stream_id
|
@@ -1,24 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'forwardable'
|
4
3
|
require 'ds9'
|
4
|
+
require 'forwardable'
|
5
5
|
require 'grpc_kit/session/stream'
|
6
|
+
require 'grpc_kit/streams/server_stream'
|
7
|
+
require 'grpc_kit/transports/server_transport'
|
6
8
|
|
7
9
|
module GrpcKit
|
8
|
-
module
|
9
|
-
class
|
10
|
+
module Sessions
|
11
|
+
class ServerSession < DS9::Server
|
10
12
|
extend Forwardable
|
11
13
|
|
12
14
|
delegate %i[send_event recv_event] => :@io
|
13
15
|
|
14
16
|
# @params io [GrpcKit::Session::IO]
|
15
|
-
|
17
|
+
# @params dispatcher [GrpcKit::Server]
|
18
|
+
def initialize(io, dispatcher)
|
16
19
|
super() # initialize DS9::Session
|
17
20
|
|
18
21
|
@io = io
|
19
22
|
@streams = {}
|
20
23
|
@stop = false
|
21
|
-
@
|
24
|
+
@dispatcher = dispatcher
|
22
25
|
@peer_shutdowned = false
|
23
26
|
@inflights = []
|
24
27
|
end
|
@@ -26,7 +29,7 @@ module GrpcKit
|
|
26
29
|
def start
|
27
30
|
@io.wait_readable
|
28
31
|
loop do
|
29
|
-
|
32
|
+
invoke
|
30
33
|
|
31
34
|
if !want_read? && !want_write?
|
32
35
|
break
|
@@ -53,6 +56,14 @@ module GrpcKit
|
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
59
|
+
def drain
|
60
|
+
# could be race condition
|
61
|
+
@streams.each do |s|
|
62
|
+
GrpcKit.logger.debug("#{s.stream_id} is draining")
|
63
|
+
s.drain
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
56
67
|
def finish
|
57
68
|
stop
|
58
69
|
@io.close
|
@@ -64,9 +75,11 @@ module GrpcKit
|
|
64
75
|
@stop = true
|
65
76
|
end
|
66
77
|
|
67
|
-
def
|
78
|
+
def invoke
|
68
79
|
while (stream = @inflights.pop)
|
69
|
-
|
80
|
+
t = GrpcKit::Transports::ServerTransport.new(self, stream)
|
81
|
+
th = GrpcKit::Streams::ServerStream.new(t)
|
82
|
+
@dispatcher.dispatch(stream.headers.path, th)
|
70
83
|
end
|
71
84
|
end
|
72
85
|
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/status_codes'
|
4
|
+
|
5
|
+
module GrpcKit
|
6
|
+
module Streams
|
7
|
+
class ClientStream
|
8
|
+
# @params transport [GrpcKit::Transports::ClientTransport]
|
9
|
+
# @params config [GrpcKit::MethodConfig]
|
10
|
+
# @params authority [String]
|
11
|
+
def initialize(transport, config, authority:, timeout: nil)
|
12
|
+
@transport = transport
|
13
|
+
@config = config
|
14
|
+
|
15
|
+
@authority = authority
|
16
|
+
@timeout = timeout
|
17
|
+
|
18
|
+
@sent_first_msg = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_msg(data, metadata: {}, timeout: nil, last: false)
|
22
|
+
buf =
|
23
|
+
begin
|
24
|
+
@config.protobuf.encode(data)
|
25
|
+
rescue ArgumentError => e
|
26
|
+
raise GrpcKit::Errors::Internal, "Error while encoding in client: #{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
limit_size = @config.max_send_message_size
|
30
|
+
if limit_size && buf.bytesize > limit_size
|
31
|
+
raise GrpcKit::Errors::ResourceExhausted, "Sending message is too large: send=#{req.bytesize}, max=#{limit_size}"
|
32
|
+
end
|
33
|
+
|
34
|
+
if @sent_first_msg
|
35
|
+
# unless metadata.empty?
|
36
|
+
# raise 'You can attach metadata at first send_msg' # XXX
|
37
|
+
# end
|
38
|
+
@transport.write_data(buf, last: last)
|
39
|
+
else
|
40
|
+
headers = build_headers(metadata: metadata)
|
41
|
+
@transport.send_request(buf, headers, last: last)
|
42
|
+
@sent_first_msg = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def each
|
47
|
+
validate_if_request_start!
|
48
|
+
|
49
|
+
loop { yield(do_recv) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def recv_msg(last: false)
|
53
|
+
validate_if_request_start!
|
54
|
+
|
55
|
+
do_recv(last: last)
|
56
|
+
end
|
57
|
+
|
58
|
+
def close_and_recv
|
59
|
+
validate_if_request_start!
|
60
|
+
|
61
|
+
@transport.close_and_flush
|
62
|
+
check_status!
|
63
|
+
|
64
|
+
data = []
|
65
|
+
loop { data.push(do_recv) }
|
66
|
+
data
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def validate_if_request_start!
|
72
|
+
unless @sent_first_msg
|
73
|
+
raise 'You should call `send_msg` method to send data'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def do_recv(last: false)
|
78
|
+
data = @transport.read_data(last: last)
|
79
|
+
|
80
|
+
if data.nil?
|
81
|
+
check_status!
|
82
|
+
raise StopIteration
|
83
|
+
end
|
84
|
+
|
85
|
+
compressed, size, buf = *data
|
86
|
+
|
87
|
+
unless size == buf.size
|
88
|
+
raise "inconsistent data: #{buf}"
|
89
|
+
end
|
90
|
+
|
91
|
+
limit_size = @config.max_receive_message_size
|
92
|
+
if limit_size && size > limit_size
|
93
|
+
raise GrpcKit::Errors::ResourceExhausted, "Receving message is too large: recevied=#{size}, max=#{limit_size}"
|
94
|
+
end
|
95
|
+
|
96
|
+
if compressed
|
97
|
+
raise 'compress option is unsupported'
|
98
|
+
end
|
99
|
+
|
100
|
+
raise StopIteration if buf.nil?
|
101
|
+
|
102
|
+
begin
|
103
|
+
@config.protobuf.decode(buf)
|
104
|
+
rescue ArgumentError => e
|
105
|
+
raise GrpcKit::Errors::Internal, "Error while decoding in Client: #{e}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_status!
|
110
|
+
headers = @transport.recv_headers
|
111
|
+
|
112
|
+
if headers.grpc_status != GrpcKit::StatusCodes::OK
|
113
|
+
raise GrpcKit::Errors.from_status_code(headers.grpc_status, headers.status_message)
|
114
|
+
else
|
115
|
+
GrpcKit.logger.debug('request is success')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def build_headers(metadata: {}, **headers)
|
120
|
+
# TODO: an order of Headers is important?
|
121
|
+
hdrs = {
|
122
|
+
':method' => 'POST',
|
123
|
+
':scheme' => 'http',
|
124
|
+
':path' => @config.path,
|
125
|
+
':authority' => @authority,
|
126
|
+
'grpc-timeout' => @timeout,
|
127
|
+
'te' => 'trailers',
|
128
|
+
'content-type' => 'application/grpc',
|
129
|
+
'user-agent' => "grpc-ruby/#{GrpcKit::VERSION} (grpc_kit)",
|
130
|
+
'grpc-accept-encoding' => 'identity,deflate,gzip',
|
131
|
+
}.merge(headers)
|
132
|
+
|
133
|
+
metadata.each do |k, v|
|
134
|
+
if k.start_with?('grpc-')
|
135
|
+
# https://github.com/grpc/grpc/blob/ffac9d90b18cb076b1c952faa55ce4e049cbc9a6/doc/PROTOCOL-HTTP2.md
|
136
|
+
GrpcKit.logger.info("metadata name wich starts with 'grpc-' is reserved for future GRPC")
|
137
|
+
else
|
138
|
+
hdrs[k] = v
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
hdrs.compact
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grpc_kit/status_codes'
|
4
|
+
|
5
|
+
module GrpcKit
|
6
|
+
module Streams
|
7
|
+
class ServerStream
|
8
|
+
# @params transport [GrpcKit::transports::ServerTransport]
|
9
|
+
def initialize(transport)
|
10
|
+
@transport = transport
|
11
|
+
@sent_first_msg = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def invoke(rpc)
|
15
|
+
rpc.invoke(self, metadata: @transport.recv_headers.metadata)
|
16
|
+
rescue GrpcKit::Errors::BadStatus => e
|
17
|
+
GrpcKit.logger.debug(e)
|
18
|
+
send_status(status: e.code, msg: e.reason, metadata: {}) # TODO: metadata should be set
|
19
|
+
rescue StandardError => e
|
20
|
+
GrpcKit.logger.debug(e)
|
21
|
+
send_status(status: GrpcKit::StatusCodes::UNKNOWN, msg: e.message, metadata: {})
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_msg(data, protobuf, last: false, limit_size: nil)
|
25
|
+
if last
|
26
|
+
send_trailer # TODO: pass trailer metadata
|
27
|
+
end
|
28
|
+
|
29
|
+
buf =
|
30
|
+
begin
|
31
|
+
protobuf.encode(data)
|
32
|
+
rescue ArgumentError => e
|
33
|
+
raise GrpcKit::Errors::Internal, "Error while encoding in server: #{e}"
|
34
|
+
end
|
35
|
+
|
36
|
+
if limit_size && buf.bytesize > limit_size
|
37
|
+
raise GrpcKit::Errors::ResourceExhausted, "Sending message is too large: send=#{req.bytesize}, max=#{limit_size}"
|
38
|
+
end
|
39
|
+
|
40
|
+
@transport.write_data(buf, last: last)
|
41
|
+
return if @sent_first_msg
|
42
|
+
|
43
|
+
send_response({})
|
44
|
+
@sent_first_msg = true
|
45
|
+
end
|
46
|
+
|
47
|
+
def recv_msg(protobuf, last: false, limit_size: nil)
|
48
|
+
data = @transport.read_data(last: last)
|
49
|
+
|
50
|
+
raise StopIteration if data.nil?
|
51
|
+
|
52
|
+
compressed, size, buf = *data
|
53
|
+
|
54
|
+
unless size == buf.size
|
55
|
+
raise "inconsistent data: #{buf}"
|
56
|
+
end
|
57
|
+
|
58
|
+
if limit_size && size > limit_size
|
59
|
+
raise GrpcKit::Errors::ResourceExhausted, "Receving message is too large: recevied=#{size}, max=#{limit_size}"
|
60
|
+
end
|
61
|
+
|
62
|
+
if compressed
|
63
|
+
raise 'compress option is unsupported'
|
64
|
+
end
|
65
|
+
|
66
|
+
raise StopIteration if buf.nil?
|
67
|
+
|
68
|
+
begin
|
69
|
+
protobuf.decode(buf)
|
70
|
+
rescue ArgumentError => e
|
71
|
+
raise GrpcKit::Errors::Internal, "Error while decoding in Server: #{e}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def each
|
76
|
+
loop { yield(recv) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def send_status(status: GrpcKit::StatusCodes::INTERNAL, msg: nil, metadata: {})
|
80
|
+
send_trailer(status: status, msg: msg, metadata: metadata)
|
81
|
+
return if @sent_first_msg
|
82
|
+
|
83
|
+
send_response({})
|
84
|
+
@sent_first_msg = true
|
85
|
+
end
|
86
|
+
|
87
|
+
def send_trailer(status: GrpcKit::StatusCodes::OK, msg: nil, metadata: {})
|
88
|
+
trailer = metadata.dup
|
89
|
+
trailer['grpc-status'] = status.to_s
|
90
|
+
if msg
|
91
|
+
trailer['grpc-message'] = msg
|
92
|
+
end
|
93
|
+
|
94
|
+
@transport.write_trailers_data(trailer)
|
95
|
+
end
|
96
|
+
|
97
|
+
def send_response(headers)
|
98
|
+
h = { ':status' => '200', 'content-type' => 'application/grpc' }.merge(headers)
|
99
|
+
h['accept-encoding'] = 'identity'
|
100
|
+
|
101
|
+
@transport.send_response(h)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|