grpc 1.6.7-x86-linux → 1.7.0.pre1-x86-linux

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/grpc_c.32.ruby +0 -0
  3. data/grpc_c.64.ruby +0 -0
  4. data/src/ruby/ext/grpc/rb_call_credentials.c +6 -2
  5. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  6. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +30 -20
  7. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +50 -35
  8. data/src/ruby/lib/grpc.rb +1 -0
  9. data/src/ruby/lib/grpc/2.0/grpc_c.so +0 -0
  10. data/src/ruby/lib/grpc/2.1/grpc_c.so +0 -0
  11. data/src/ruby/lib/grpc/2.2/grpc_c.so +0 -0
  12. data/src/ruby/lib/grpc/2.3/grpc_c.so +0 -0
  13. data/src/ruby/lib/grpc/2.4/grpc_c.so +0 -0
  14. data/src/ruby/lib/grpc/generic/active_call.rb +34 -9
  15. data/src/ruby/lib/grpc/generic/bidi_call.rb +19 -10
  16. data/src/ruby/lib/grpc/generic/client_stub.rb +95 -38
  17. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  18. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  19. data/src/ruby/lib/grpc/generic/rpc_desc.rb +66 -20
  20. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -3
  21. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +1 -2
  22. data/src/ruby/lib/grpc/grpc_c.so +0 -0
  23. data/src/ruby/lib/grpc/version.rb +1 -1
  24. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +1 -0
  25. data/src/ruby/spec/channel_connection_spec.rb +1 -34
  26. data/src/ruby/spec/client_server_spec.rb +188 -82
  27. data/src/ruby/spec/generic/active_call_spec.rb +65 -11
  28. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  29. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  30. data/src/ruby/spec/generic/rpc_desc_spec.rb +38 -0
  31. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -34
  32. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  33. data/src/ruby/spec/spec_helper.rb +4 -0
  34. data/src/ruby/spec/support/helpers.rb +73 -0
  35. data/src/ruby/spec/support/services.rb +147 -0
  36. metadata +24 -12
@@ -89,17 +89,23 @@ module GRPC
89
89
  # used within a gRPC server.
90
90
  # @param channel_args [Hash] the channel arguments. Note: this argument is
91
91
  # ignored if the channel_override argument is provided.
92
+ # @param interceptors [Array<GRPC::ClientInterceptor>] An array of
93
+ # GRPC::ClientInterceptor objects that will be used for
94
+ # intercepting calls before they are executed
95
+ # Interceptors are an EXPERIMENTAL API.
92
96
  def initialize(host, creds,
93
97
  channel_override: nil,
94
98
  timeout: nil,
95
99
  propagate_mask: nil,
96
- channel_args: {})
100
+ channel_args: {},
101
+ interceptors: [])
97
102
  @ch = ClientStub.setup_channel(channel_override, host, creds,
98
103
  channel_args)
99
104
  alt_host = channel_args[Core::Channel::SSL_TARGET]
100
105
  @host = alt_host.nil? ? host : alt_host
101
106
  @propagate_mask = propagate_mask
102
107
  @timeout = timeout.nil? ? DEFAULT_TIMEOUT : timeout
108
+ @interceptors = InterceptorRegistry.new(interceptors)
103
109
  end
104
110
 
105
111
  # request_response sends a request to a GRPC server, and returns the
@@ -149,16 +155,29 @@ module GRPC
149
155
  deadline: deadline,
150
156
  parent: parent,
151
157
  credentials: credentials)
152
- return c.request_response(req, metadata: metadata) unless return_op
153
-
154
- # return the operation view of the active_call; define #execute as a
155
- # new method for this instance that invokes #request_response.
156
- c.merge_metadata_to_send(metadata)
157
- op = c.operation
158
- op.define_singleton_method(:execute) do
159
- c.request_response(req, metadata: metadata)
158
+ interception_context = @interceptors.build_context
159
+ intercept_args = {
160
+ method: method,
161
+ request: req,
162
+ call: c.interceptable,
163
+ metadata: metadata
164
+ }
165
+ if return_op
166
+ # return the operation view of the active_call; define #execute as a
167
+ # new method for this instance that invokes #request_response.
168
+ c.merge_metadata_to_send(metadata)
169
+ op = c.operation
170
+ op.define_singleton_method(:execute) do
171
+ interception_context.intercept!(:request_response, intercept_args) do
172
+ c.request_response(req, metadata: metadata)
173
+ end
174
+ end
175
+ op
176
+ else
177
+ interception_context.intercept!(:request_response, intercept_args) do
178
+ c.request_response(req, metadata: metadata)
179
+ end
160
180
  end
161
- op
162
181
  end
163
182
 
164
183
  # client_streamer sends a stream of requests to a GRPC server, and
@@ -213,16 +232,29 @@ module GRPC
213
232
  deadline: deadline,
214
233
  parent: parent,
215
234
  credentials: credentials)
216
- return c.client_streamer(requests, metadata: metadata) unless return_op
217
-
218
- # return the operation view of the active_call; define #execute as a
219
- # new method for this instance that invokes #client_streamer.
220
- c.merge_metadata_to_send(metadata)
221
- op = c.operation
222
- op.define_singleton_method(:execute) do
223
- c.client_streamer(requests)
235
+ interception_context = @interceptors.build_context
236
+ intercept_args = {
237
+ method: method,
238
+ requests: requests,
239
+ call: c.interceptable,
240
+ metadata: metadata
241
+ }
242
+ if return_op
243
+ # return the operation view of the active_call; define #execute as a
244
+ # new method for this instance that invokes #client_streamer.
245
+ c.merge_metadata_to_send(metadata)
246
+ op = c.operation
247
+ op.define_singleton_method(:execute) do
248
+ interception_context.intercept!(:client_streamer, intercept_args) do
249
+ c.client_streamer(requests)
250
+ end
251
+ end
252
+ op
253
+ else
254
+ interception_context.intercept!(:client_streamer, intercept_args) do
255
+ c.client_streamer(requests, metadata: metadata)
256
+ end
224
257
  end
225
- op
226
258
  end
227
259
 
228
260
  # server_streamer sends one request to the GRPC server, which yields a
@@ -292,16 +324,29 @@ module GRPC
292
324
  deadline: deadline,
293
325
  parent: parent,
294
326
  credentials: credentials)
295
- return c.server_streamer(req, metadata: metadata, &blk) unless return_op
296
-
297
- # return the operation view of the active_call; define #execute
298
- # as a new method for this instance that invokes #server_streamer
299
- c.merge_metadata_to_send(metadata)
300
- op = c.operation
301
- op.define_singleton_method(:execute) do
302
- c.server_streamer(req, &blk)
327
+ interception_context = @interceptors.build_context
328
+ intercept_args = {
329
+ method: method,
330
+ request: req,
331
+ call: c.interceptable,
332
+ metadata: metadata
333
+ }
334
+ if return_op
335
+ # return the operation view of the active_call; define #execute
336
+ # as a new method for this instance that invokes #server_streamer
337
+ c.merge_metadata_to_send(metadata)
338
+ op = c.operation
339
+ op.define_singleton_method(:execute) do
340
+ interception_context.intercept!(:server_streamer, intercept_args) do
341
+ c.server_streamer(req, &blk)
342
+ end
343
+ end
344
+ op
345
+ else
346
+ interception_context.intercept!(:server_streamer, intercept_args) do
347
+ c.server_streamer(req, metadata: metadata, &blk)
348
+ end
303
349
  end
304
- op
305
350
  end
306
351
 
307
352
  # bidi_streamer sends a stream of requests to the GRPC server, and yields
@@ -405,17 +450,29 @@ module GRPC
405
450
  deadline: deadline,
406
451
  parent: parent,
407
452
  credentials: credentials)
408
- return c.bidi_streamer(requests, metadata: metadata,
409
- &blk) unless return_op
410
-
411
- # return the operation view of the active_call; define #execute
412
- # as a new method for this instance that invokes #bidi_streamer
413
- c.merge_metadata_to_send(metadata)
414
- op = c.operation
415
- op.define_singleton_method(:execute) do
416
- c.bidi_streamer(requests, &blk)
453
+ interception_context = @interceptors.build_context
454
+ intercept_args = {
455
+ method: method,
456
+ requests: requests,
457
+ call: c.interceptable,
458
+ metadata: metadata
459
+ }
460
+ if return_op
461
+ # return the operation view of the active_call; define #execute
462
+ # as a new method for this instance that invokes #bidi_streamer
463
+ c.merge_metadata_to_send(metadata)
464
+ op = c.operation
465
+ op.define_singleton_method(:execute) do
466
+ interception_context.intercept!(:bidi_streamer, intercept_args) do
467
+ c.bidi_streamer(requests, &blk)
468
+ end
469
+ end
470
+ op
471
+ else
472
+ interception_context.intercept!(:bidi_streamer, intercept_args) do
473
+ c.bidi_streamer(requests, metadata: metadata, &blk)
474
+ end
417
475
  end
418
- op
419
476
  end
420
477
 
421
478
  private
@@ -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}")