grpc 1.6.7-universal-darwin → 1.7.0.pre1-universal-darwin

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/src/ruby/ext/grpc/rb_call_credentials.c +6 -2
  3. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  4. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +30 -20
  5. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +50 -35
  6. data/src/ruby/lib/grpc.rb +1 -0
  7. data/src/ruby/lib/grpc/2.0/grpc_c.bundle +0 -0
  8. data/src/ruby/lib/grpc/2.1/grpc_c.bundle +0 -0
  9. data/src/ruby/lib/grpc/2.2/grpc_c.bundle +0 -0
  10. data/src/ruby/lib/grpc/2.3/grpc_c.bundle +0 -0
  11. data/src/ruby/lib/grpc/2.4/grpc_c.bundle +0 -0
  12. data/src/ruby/lib/grpc/generic/active_call.rb +34 -9
  13. data/src/ruby/lib/grpc/generic/bidi_call.rb +19 -10
  14. data/src/ruby/lib/grpc/generic/client_stub.rb +95 -38
  15. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  16. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  17. data/src/ruby/lib/grpc/generic/rpc_desc.rb +66 -20
  18. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -3
  19. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +1 -2
  20. data/src/ruby/lib/grpc/version.rb +1 -1
  21. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +1 -0
  22. data/src/ruby/spec/channel_connection_spec.rb +1 -34
  23. data/src/ruby/spec/client_server_spec.rb +188 -82
  24. data/src/ruby/spec/generic/active_call_spec.rb +65 -11
  25. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  26. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  27. data/src/ruby/spec/generic/rpc_desc_spec.rb +38 -0
  28. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -34
  29. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  30. data/src/ruby/spec/spec_helper.rb +4 -0
  31. data/src/ruby/spec/support/helpers.rb +73 -0
  32. data/src/ruby/spec/support/services.rb +147 -0
  33. metadata +24 -12
@@ -0,0 +1,53 @@
1
+ # Copyright 2017 gRPC authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # GRPC contains the General RPC module.
16
+ module GRPC
17
+ ##
18
+ # Represents a registry of added interceptors available for enumeration.
19
+ # The registry can be used for both server and client interceptors.
20
+ # This class is internal to gRPC and not meant for public usage.
21
+ #
22
+ class InterceptorRegistry
23
+ ##
24
+ # An error raised when an interceptor is attempted to be added
25
+ # that does not extend GRPC::Interceptor
26
+ #
27
+ class DescendantError < StandardError; end
28
+
29
+ ##
30
+ # Initialize the registry with an empty interceptor list
31
+ # This is an EXPERIMENTAL API.
32
+ #
33
+ def initialize(interceptors = [])
34
+ @interceptors = []
35
+ interceptors.each do |i|
36
+ base = GRPC::Interceptor
37
+ unless i.class.ancestors.include?(base)
38
+ fail DescendantError, "Interceptors must descend from #{base}"
39
+ end
40
+ @interceptors << i
41
+ end
42
+ end
43
+
44
+ ##
45
+ # Builds an interception context from this registry
46
+ #
47
+ # @return [InterceptionContext]
48
+ #
49
+ def build_context
50
+ InterceptionContext.new(@interceptors)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,186 @@
1
+ # Copyright 2017 gRPC authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require_relative 'interceptor_registry'
15
+
16
+ # GRPC contains the General RPC module.
17
+ module GRPC
18
+ ##
19
+ # Base class for interception in GRPC
20
+ #
21
+ class Interceptor
22
+ ##
23
+ # @param [Hash] options A hash of options that will be used
24
+ # by the interceptor. This is an EXPERIMENTAL API.
25
+ #
26
+ def initialize(options = {})
27
+ @options = options || {}
28
+ end
29
+ end
30
+
31
+ ##
32
+ # ClientInterceptor allows for wrapping outbound gRPC client stub requests.
33
+ # This is an EXPERIMENTAL API.
34
+ #
35
+ class ClientInterceptor < Interceptor
36
+ ##
37
+ # Intercept a unary request response call
38
+ #
39
+ # @param [Object] request
40
+ # @param [GRPC::ActiveCall] call
41
+ # @param [Method] method
42
+ # @param [Hash] metadata
43
+ #
44
+ def request_response(request:, call:, method:, metadata:)
45
+ GRPC.logger.debug "Intercepting request response method #{method}" \
46
+ " for request #{request} with call #{call} and metadata: #{metadata}"
47
+ yield
48
+ end
49
+
50
+ ##
51
+ # Intercept a client streaming call
52
+ #
53
+ # @param [Enumerable] requests
54
+ # @param [GRPC::ActiveCall] call
55
+ # @param [Method] method
56
+ # @param [Hash] metadata
57
+ #
58
+ def client_streamer(requests:, call:, method:, metadata:)
59
+ GRPC.logger.debug "Intercepting client streamer method #{method}" \
60
+ " for requests #{requests} with call #{call} and metadata: #{metadata}"
61
+ yield
62
+ end
63
+
64
+ ##
65
+ # Intercept a server streaming call
66
+ #
67
+ # @param [Object] request
68
+ # @param [GRPC::ActiveCall] call
69
+ # @param [Method] method
70
+ # @param [Hash] metadata
71
+ #
72
+ def server_streamer(request:, call:, method:, metadata:)
73
+ GRPC.logger.debug "Intercepting server streamer method #{method}" \
74
+ " for request #{request} with call #{call} and metadata: #{metadata}"
75
+ yield
76
+ end
77
+
78
+ ##
79
+ # Intercept a BiDi streaming call
80
+ #
81
+ # @param [Enumerable] requests
82
+ # @param [GRPC::ActiveCall] call
83
+ # @param [Method] method
84
+ # @param [Hash] metadata
85
+ #
86
+ def bidi_streamer(requests:, call:, method:, metadata:)
87
+ GRPC.logger.debug "Intercepting bidi streamer method #{method}" \
88
+ " for requests #{requests} with call #{call} and metadata: #{metadata}"
89
+ yield
90
+ end
91
+ end
92
+
93
+ ##
94
+ # ServerInterceptor allows for wrapping gRPC server execution handling.
95
+ # This is an EXPERIMENTAL API.
96
+ #
97
+ class ServerInterceptor < Interceptor
98
+ ##
99
+ # Intercept a unary request response call.
100
+ #
101
+ # @param [Object] request
102
+ # @param [GRPC::ActiveCall::SingleReqView] call
103
+ # @param [Method] method
104
+ #
105
+ def request_response(request:, call:, method:)
106
+ GRPC.logger.debug "Intercepting request response method #{method}" \
107
+ " for request #{request} with call #{call}"
108
+ yield
109
+ end
110
+
111
+ ##
112
+ # Intercept a client streaming call
113
+ #
114
+ # @param [GRPC::ActiveCall::MultiReqView] call
115
+ # @param [Method] method
116
+ #
117
+ def client_streamer(call:, method:)
118
+ GRPC.logger.debug "Intercepting client streamer method #{method}" \
119
+ " with call #{call}"
120
+ yield
121
+ end
122
+
123
+ ##
124
+ # Intercept a server streaming call
125
+ #
126
+ # @param [Object] request
127
+ # @param [GRPC::ActiveCall::SingleReqView] call
128
+ # @param [Method] method
129
+ #
130
+ def server_streamer(request:, call:, method:)
131
+ GRPC.logger.debug "Intercepting server streamer method #{method}" \
132
+ " for request #{request} with call #{call}"
133
+ yield
134
+ end
135
+
136
+ ##
137
+ # Intercept a BiDi streaming call
138
+ #
139
+ # @param [Enumerable<Object>] requests
140
+ # @param [GRPC::ActiveCall::MultiReqView] call
141
+ # @param [Method] method
142
+ #
143
+ def bidi_streamer(requests:, call:, method:)
144
+ GRPC.logger.debug "Intercepting bidi streamer method #{method}" \
145
+ " for requests #{requests} with call #{call}"
146
+ yield
147
+ end
148
+ end
149
+
150
+ ##
151
+ # Represents the context in which an interceptor runs. Used to provide an
152
+ # injectable mechanism for handling interception. This is an EXPERIMENTAL API.
153
+ #
154
+ class InterceptionContext
155
+ ##
156
+ # @param [Array<GRPC::Interceptor>]
157
+ #
158
+ def initialize(interceptors = [])
159
+ @interceptors = interceptors.dup
160
+ end
161
+
162
+ ##
163
+ # Intercept the call and fire out to interceptors in a FIFO execution.
164
+ # This is an EXPERIMENTAL API.
165
+ #
166
+ # @param [Symbol] type The request type
167
+ # @param [Hash] args The arguments for the call
168
+ #
169
+ def intercept!(type, args = {})
170
+ return yield if @interceptors.none?
171
+
172
+ i = @interceptors.pop
173
+ return yield unless i
174
+
175
+ i.send(type, args) do
176
+ if @interceptors.any?
177
+ intercept!(type, args) do
178
+ yield
179
+ end
180
+ else
181
+ yield
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -47,43 +47,85 @@ module GRPC
47
47
  proc { |o| unmarshal_class.method(unmarshal_method).call(o) }
48
48
  end
49
49
 
50
- def handle_request_response(active_call, mth)
50
+ def handle_request_response(active_call, mth, inter_ctx)
51
51
  req = active_call.read_unary_request
52
- resp = mth.call(req, active_call.single_req_view)
53
- active_call.server_unary_response(
54
- resp, trailing_metadata: active_call.output_metadata)
52
+ call = active_call.single_req_view
53
+
54
+ inter_ctx.intercept!(
55
+ :request_response,
56
+ method: mth,
57
+ call: call,
58
+ request: req
59
+ ) do
60
+ resp = mth.call(req, call)
61
+ active_call.server_unary_response(
62
+ resp,
63
+ trailing_metadata: active_call.output_metadata
64
+ )
65
+ end
55
66
  end
56
67
 
57
- def handle_client_streamer(active_call, mth)
58
- resp = mth.call(active_call.multi_req_view)
59
- active_call.server_unary_response(
60
- resp, trailing_metadata: active_call.output_metadata)
68
+ def handle_client_streamer(active_call, mth, inter_ctx)
69
+ call = active_call.multi_req_view
70
+
71
+ inter_ctx.intercept!(
72
+ :client_streamer,
73
+ method: mth,
74
+ call: call
75
+ ) do
76
+ resp = mth.call(call)
77
+ active_call.server_unary_response(
78
+ resp,
79
+ trailing_metadata: active_call.output_metadata
80
+ )
81
+ end
61
82
  end
62
83
 
63
- def handle_server_streamer(active_call, mth)
84
+ def handle_server_streamer(active_call, mth, inter_ctx)
64
85
  req = active_call.read_unary_request
65
- replys = mth.call(req, active_call.single_req_view)
66
- replys.each { |r| active_call.remote_send(r) }
67
- send_status(active_call, OK, 'OK', active_call.output_metadata)
86
+ call = active_call.single_req_view
87
+
88
+ inter_ctx.intercept!(
89
+ :server_streamer,
90
+ method: mth,
91
+ call: call,
92
+ request: req
93
+ ) do
94
+ replies = mth.call(req, call)
95
+ replies.each { |r| active_call.remote_send(r) }
96
+ send_status(active_call, OK, 'OK', active_call.output_metadata)
97
+ end
68
98
  end
69
99
 
70
- def handle_bidi_streamer(active_call, mth)
71
- active_call.run_server_bidi(mth)
100
+ ##
101
+ # @param [GRPC::ActiveCall] active_call
102
+ # @param [Method] mth
103
+ # @param [Array<GRPC::InterceptionContext>] inter_ctx
104
+ #
105
+ def handle_bidi_streamer(active_call, mth, inter_ctx)
106
+ active_call.run_server_bidi(mth, inter_ctx)
72
107
  send_status(active_call, OK, 'OK', active_call.output_metadata)
73
108
  end
74
109
 
75
- def run_server_method(active_call, mth)
110
+ ##
111
+ # @param [GRPC::ActiveCall] active_call The current active call object
112
+ # for the request
113
+ # @param [Method] mth The current RPC method being called
114
+ # @param [GRPC::InterceptionContext] inter_ctx The interception context
115
+ # being executed
116
+ #
117
+ def run_server_method(active_call, mth, inter_ctx = InterceptionContext.new)
76
118
  # While a server method is running, it might be cancelled, its deadline
77
119
  # might be reached, the handler could throw an unknown error, or a
78
120
  # well-behaved handler could throw a StatusError.
79
121
  if request_response?
80
- handle_request_response(active_call, mth)
122
+ handle_request_response(active_call, mth, inter_ctx)
81
123
  elsif client_streamer?
82
- handle_client_streamer(active_call, mth)
124
+ handle_client_streamer(active_call, mth, inter_ctx)
83
125
  elsif server_streamer?
84
- handle_server_streamer(active_call, mth)
126
+ handle_server_streamer(active_call, mth, inter_ctx)
85
127
  else # is a bidi_stream
86
- handle_bidi_streamer(active_call, mth)
128
+ handle_bidi_streamer(active_call, mth, inter_ctx)
87
129
  end
88
130
  rescue BadStatus => e
89
131
  # this is raised by handlers that want GRPC to send an application error
@@ -99,9 +141,13 @@ module GRPC
99
141
  # event. Send a status of deadline exceeded
100
142
  GRPC.logger.warn("late call: #{active_call}")
101
143
  send_status(active_call, DEADLINE_EXCEEDED, 'late')
102
- rescue StandardError => e
144
+ rescue StandardError, NotImplementedError => e
103
145
  # This will usuaally be an unhandled error in the handling code.
104
146
  # Send back a UNKNOWN status to the client
147
+ #
148
+ # Note: this intentionally does not map NotImplementedError to
149
+ # UNIMPLEMENTED because NotImplementedError is intended for low-level
150
+ # OS interaction (e.g. syscalls) not supported by the current OS.
105
151
  GRPC.logger.warn("failed handler: #{active_call}; sending status:UNKNOWN")
106
152
  GRPC.logger.warn(e)
107
153
  send_status(active_call, UNKNOWN, "#{e.class}: #{e.message}")
@@ -196,11 +196,18 @@ module GRPC
196
196
  #
197
197
  # * server_args:
198
198
  # A server arguments hash to be passed down to the underlying core server
199
+ #
200
+ # * interceptors:
201
+ # Am array of GRPC::ServerInterceptor objects that will be used for
202
+ # intercepting server handlers to provide extra functionality.
203
+ # Interceptors are an EXPERIMENTAL API.
204
+ #
199
205
  def initialize(pool_size:DEFAULT_POOL_SIZE,
200
206
  max_waiting_requests:DEFAULT_MAX_WAITING_REQUESTS,
201
207
  poll_period:DEFAULT_POLL_PERIOD,
202
208
  connect_md_proc:nil,
203
- server_args:{})
209
+ server_args:{},
210
+ interceptors:[])
204
211
  @connect_md_proc = RpcServer.setup_connect_md_proc(connect_md_proc)
205
212
  @max_waiting_requests = max_waiting_requests
206
213
  @poll_period = poll_period
@@ -212,6 +219,7 @@ module GRPC
212
219
  # :stopped. State transitions can only proceed in that order.
213
220
  @running_state = :not_started
214
221
  @server = Core::Server.new(server_args)
222
+ @interceptors = InterceptorRegistry.new(interceptors)
215
223
  end
216
224
 
217
225
  # stops a running server
@@ -374,7 +382,11 @@ module GRPC
374
382
  @pool.schedule(active_call) do |ac|
375
383
  c, mth = ac
376
384
  begin
377
- rpc_descs[mth].run_server_method(c, rpc_handlers[mth])
385
+ rpc_descs[mth].run_server_method(
386
+ c,
387
+ rpc_handlers[mth],
388
+ @interceptors.build_context
389
+ )
378
390
  rescue StandardError
379
391
  c.send_status(GRPC::Core::StatusCodes::INTERNAL,
380
392
  'Server handler failed')
@@ -382,7 +394,7 @@ module GRPC
382
394
  end
383
395
  end
384
396
  rescue Core::CallError, RuntimeError => e
385
- # these might happen for various reasonse. The correct behaviour of
397
+ # these might happen for various reasons. The correct behavior of
386
398
  # the server is to log them and continue, if it's not shutting down.
387
399
  if running_state == :running
388
400
  GRPC.logger.warn("server call failed: #{e}")
@@ -29,8 +29,7 @@ module GRPC
29
29
  fail ArgumentError, 'bad type' unless status.is_a? Struct::Status
30
30
  grpc_status_details_bin_trailer = 'grpc-status-details-bin'
31
31
  return nil if status.metadata[grpc_status_details_bin_trailer].nil?
32
- Google::Rpc::Status.decode(
33
- status.metadata[grpc_status_details_bin_trailer])
32
+ Google::Rpc::Status.decode(status.metadata[grpc_status_details_bin_trailer])
34
33
  end
35
34
  end
36
35
  end
@@ -14,5 +14,5 @@
14
14
 
15
15
  # GRPC contains the General RPC module.
16
16
  module GRPC
17
- VERSION = '1.6.7'
17
+ VERSION = '1.7.0.pre1'
18
18
  end
@@ -34,6 +34,7 @@ module Grpc
34
34
  self.service_name = 'grpc.testing.duplicate.EchoTestService'
35
35
 
36
36
  rpc :Echo, Grpc::Testing::EchoRequest, Grpc::Testing::EchoResponse
37
+ rpc :ResponseStream, Grpc::Testing::EchoRequest, stream(Grpc::Testing::EchoResponse)
37
38
  end
38
39
 
39
40
  Stub = Service.rpc_stub_class
@@ -11,45 +11,12 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
- require 'grpc'
14
+ require 'spec_helper'
16
15
  require 'timeout'
17
16
 
18
17
  include Timeout
19
18
  include GRPC::Core
20
19
 
21
- # A test message
22
- class EchoMsg
23
- def self.marshal(_o)
24
- ''
25
- end
26
-
27
- def self.unmarshal(_o)
28
- EchoMsg.new
29
- end
30
- end
31
-
32
- # A test service with an echo implementation.
33
- class EchoService
34
- include GRPC::GenericService
35
- rpc :an_rpc, EchoMsg, EchoMsg
36
- attr_reader :received_md
37
-
38
- def initialize(**kw)
39
- @trailing_metadata = kw
40
- @received_md = []
41
- end
42
-
43
- def an_rpc(req, call)
44
- GRPC.logger.info('echo service received a request')
45
- call.output_metadata.update(@trailing_metadata)
46
- @received_md << call.metadata unless call.metadata.nil?
47
- req
48
- end
49
- end
50
-
51
- EchoStub = EchoService.rpc_stub_class
52
-
53
20
  def start_server(port = 0)
54
21
  @srv = GRPC::RpcServer.new(pool_size: 1)
55
22
  server_port = @srv.add_http2_port("localhost:#{port}", :this_port_is_insecure)