grpc 0.9.4 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/.rubocop_todo.yml +1 -1
- data/README.md +41 -39
- data/bin/interop/interop_client.rb +4 -1
- data/bin/interop/interop_server.rb +5 -2
- data/ext/grpc/extconf.rb +43 -32
- data/ext/grpc/rb_byte_buffer.c +5 -4
- data/ext/grpc/rb_call.c +1 -0
- data/ext/grpc/rb_completion_queue.c +10 -2
- data/ext/grpc/rb_server.c +61 -9
- data/grpc.gemspec +1 -1
- data/lib/grpc/generic/active_call.rb +27 -6
- data/lib/grpc/generic/bidi_call.rb +47 -39
- data/lib/grpc/generic/rpc_desc.rb +1 -0
- data/lib/grpc/generic/rpc_server.rb +8 -5
- data/lib/grpc/logconfig.rb +1 -1
- data/lib/grpc/version.rb +1 -1
- data/spec/client_server_spec.rb +55 -14
- data/spec/generic/active_call_spec.rb +1 -1
- data/spec/generic/client_stub_spec.rb +2 -1
- data/spec/generic/rpc_server_spec.rb +0 -12
- data/spec/server_spec.rb +11 -11
- data/spec/spec_helper.rb +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 296a3415a75bad4a6d252472eea237cc77517ca0
|
4
|
+
data.tar.gz: facb8556323b3884eb64b8d9cf9332ee18502eed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 416c3b38ba0f659d6bf05fcc794a88fd7142a72f9b313229ffeb1d7f1adcf0d80ae78454ae38fc1e4d587f9ce430131f06d81d3dc7c028a7a69f800ab1ea8a1f
|
7
|
+
data.tar.gz: be7d80cafebe1a21aa9fa4f0f3fd1b19a447fffa641c2828f11de540e371157e39673b9841f07d9a1f251d41050160a6f3f7d181cceb09fd7e5ab77cb31d700d
|
data/.rspec
CHANGED
data/.rubocop_todo.yml
CHANGED
data/README.md
CHANGED
@@ -4,48 +4,44 @@ gRPC Ruby
|
|
4
4
|
A Ruby implementation of gRPC.
|
5
5
|
|
6
6
|
Status
|
7
|
-
|
7
|
+
------
|
8
8
|
|
9
9
|
Alpha : Ready for early adopters
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
PREREQUISITES
|
12
|
+
-------------
|
13
13
|
|
14
|
-
|
14
|
+
- Ruby 2.x. The gRPC API uses keyword args.
|
15
|
+
- [homebrew][] on Mac OS X, [linuxbrew][] on Linux. These simplify the installation of the gRPC C core.
|
15
16
|
|
16
|
-
|
17
|
-
QUICK - INSTALL
|
17
|
+
INSTALLATION
|
18
18
|
---------------
|
19
|
-
|
20
|
-
|
21
|
-
- Follow the instructions in [INSTALL](../../INSTALL) to install the gRPC C core.
|
22
|
-
- If you don't have Ruby 2.1 installed, switch to the more detailed instructions below
|
23
|
-
- Use bundler to install
|
19
|
+
On Mac OS X, install [homebrew][]. On Linux, install [linuxbrew][].
|
20
|
+
Run the following command to install gRPC Ruby.
|
24
21
|
```sh
|
25
|
-
$
|
26
|
-
$ gem install bundler && bundle install
|
22
|
+
$ curl -fsSL https://goo.gl/getgrpc | bash -s ruby
|
27
23
|
```
|
24
|
+
This will download and run the [gRPC install script][], then install the latest version of gRPC Ruby gem. It also installs Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin for ruby.
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
BUILD FROM SOURCE
|
27
|
+
---------------------
|
28
|
+
- Clone this repository
|
32
29
|
- Build the gRPC C core
|
33
|
-
E.g, from the root of the gRPC [
|
30
|
+
E.g, from the root of the gRPC [Git repository](https://github.com/google/grpc)
|
34
31
|
```sh
|
35
32
|
$ cd ../..
|
36
33
|
$ make && sudo make install
|
37
34
|
```
|
38
35
|
|
39
|
-
- Install Ruby 2.
|
36
|
+
- Install Ruby 2.x. Consider doing this with [RVM](http://rvm.io), it's a nice way of controlling
|
40
37
|
the exact ruby version that's used.
|
41
38
|
```sh
|
42
39
|
$ command curl -sSL https://rvm.io/mpapis.asc | gpg --import -
|
43
|
-
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2
|
40
|
+
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2
|
44
41
|
$
|
45
42
|
$ # follow the instructions to ensure that your're using the latest stable version of Ruby
|
46
43
|
$ # and that the rvm command is installed
|
47
44
|
```
|
48
|
-
|
49
45
|
- Make sure your run `source $HOME/.rvm/scripts/rvm` as instructed to complete the set up of RVM
|
50
46
|
|
51
47
|
- Install [bundler](http://bundler.io/)
|
@@ -53,30 +49,36 @@ $ # and that the rvm command is installed
|
|
53
49
|
$ gem install bundler
|
54
50
|
```
|
55
51
|
|
56
|
-
- Finally, install the gRPC gem locally.
|
52
|
+
- Finally, build and install the gRPC gem locally.
|
57
53
|
```sh
|
58
54
|
$ # from this directory
|
59
55
|
$ bundle install # creates the ruby bundle, including building the grpc extension
|
60
56
|
$ rake # runs the unit tests, see rake -T for other options
|
61
57
|
```
|
62
58
|
|
59
|
+
DOCUMENTATION
|
60
|
+
-------------
|
61
|
+
- rubydoc for the gRPC gem is available online at [rubydoc][].
|
62
|
+
- the gRPC Ruby reference documentation is available online at [grpc.io][]
|
63
|
+
|
63
64
|
CONTENTS
|
64
65
|
--------
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
66
|
+
Directory structure is the layout for [ruby extensions][]
|
67
|
+
- ext: the gRPC ruby extension
|
68
|
+
- lib: the entrypoint gRPC ruby library to be used in a 'require' statement
|
69
|
+
- spec: Rspec unittests
|
70
|
+
- bin: example gRPC clients and servers, e.g,
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
stub = Math::Math::Stub.new('my.test.math.server.com:8080')
|
74
|
+
req = Math::DivArgs.new(dividend: 7, divisor: 3)
|
75
|
+
GRPC.logger.info("div(7/3): req=#{req.inspect}")
|
76
|
+
resp = stub.div(req)
|
77
|
+
GRPC.logger.info("Answer: #{resp.inspect}")
|
78
|
+
```
|
79
|
+
[homebrew]:http://brew.sh
|
80
|
+
[linuxbrew]:https://github.com/Homebrew/linuxbrew#installation
|
81
|
+
[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
|
82
|
+
[ruby extensions]:http://guides.rubygems.org/gems-with-extensions/
|
83
|
+
[rubydoc]: http://www.rubydoc.info/gems/grpc
|
84
|
+
[grpc.io]: http://www.grpc.io/docs/installation/ruby.html
|
@@ -274,6 +274,7 @@ class NamedTests
|
|
274
274
|
op = @stub.streaming_input_call(reqs, return_op: true)
|
275
275
|
op.cancel
|
276
276
|
assert_raises(GRPC::Cancelled) { op.execute }
|
277
|
+
assert(op.cancelled, 'call operation should be CANCELLED')
|
277
278
|
p 'OK: cancel_after_begin'
|
278
279
|
end
|
279
280
|
|
@@ -282,7 +283,9 @@ class NamedTests
|
|
282
283
|
ppp = PingPongPlayer.new(msg_sizes)
|
283
284
|
op = @stub.full_duplex_call(ppp.each_item, return_op: true)
|
284
285
|
ppp.canceller_op = op # causes ppp to cancel after the 1st message
|
285
|
-
|
286
|
+
op.execute.each { |r| ppp.queue.push(r) }
|
287
|
+
op.wait
|
288
|
+
assert(op.cancelled, 'call operation was not CANCELLED')
|
286
289
|
p 'OK: cancel_after_first_response'
|
287
290
|
end
|
288
291
|
|
@@ -128,16 +128,19 @@ class TestTarget < Grpc::Testing::TestService::Service
|
|
128
128
|
cls = StreamingOutputCallResponse
|
129
129
|
Thread.new do
|
130
130
|
begin
|
131
|
+
GRPC.logger.info('interop-server: started receiving')
|
131
132
|
reqs.each do |req|
|
132
|
-
GRPC.logger.info("read #{req.inspect}")
|
133
133
|
resp_size = req.response_parameters[0].size
|
134
|
+
GRPC.logger.info("read a req, response size is #{resp_size}")
|
134
135
|
resp = cls.new(payload: Payload.new(type: req.response_type,
|
135
136
|
body: nulls(resp_size)))
|
136
137
|
q.push(resp)
|
137
138
|
end
|
138
|
-
GRPC.logger.info('finished
|
139
|
+
GRPC.logger.info('interop-server: finished receiving')
|
139
140
|
q.push(self)
|
140
141
|
rescue StandardError => e
|
142
|
+
GRPC.logger.info('interop-server: failed')
|
143
|
+
GRPC.logger.warn(e)
|
141
144
|
q.push(e) # share the exception with the enumerator
|
142
145
|
end
|
143
146
|
end
|
data/ext/grpc/extconf.rb
CHANGED
@@ -54,44 +54,55 @@ LIB_DIRS = [
|
|
54
54
|
LIBDIR
|
55
55
|
]
|
56
56
|
|
57
|
-
|
58
|
-
grpc_root = ENV['GRPC_ROOT']
|
59
|
-
if grpc_root.nil?
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
# When grpc_root is available attempt to build the grpc core.
|
65
|
-
unless grpc_root.nil?
|
66
|
-
grpc_config = ENV['GRPC_CONFIG'] || 'opt'
|
67
|
-
if ENV.key?('GRPC_LIB_DIR')
|
68
|
-
grpc_lib_dir = File.join(grpc_root, ENV['GRPC_LIB_DIR'])
|
69
|
-
else
|
70
|
-
grpc_lib_dir = File.join(File.join(grpc_root, 'libs'), grpc_config)
|
71
|
-
end
|
72
|
-
unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a'))
|
73
|
-
system("make -C #{grpc_root} static_c CONFIG=#{grpc_config}")
|
57
|
+
def check_grpc_root
|
58
|
+
grpc_root = ENV['GRPC_ROOT']
|
59
|
+
if grpc_root.nil?
|
60
|
+
r = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
|
61
|
+
grpc_root = r if File.exist?(File.join(r, 'include/grpc/grpc.h'))
|
74
62
|
end
|
75
|
-
|
76
|
-
LIB_DIRS.unshift grpc_lib_dir
|
63
|
+
grpc_root
|
77
64
|
end
|
78
65
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
66
|
+
grpc_pkg_config = system('pkg-config --exists grpc')
|
67
|
+
|
68
|
+
if grpc_pkg_config
|
69
|
+
$CFLAGS << ' ' + `pkg-config --static --cflags grpc`.strip + ' '
|
70
|
+
$LDFLAGS << ' ' + `pkg-config --static --libs grpc`.strip + ' '
|
71
|
+
else
|
72
|
+
dir_config('grpc', HEADER_DIRS, LIB_DIRS)
|
73
|
+
fail 'libdl not found' unless have_library('dl', 'dlopen')
|
74
|
+
fail 'zlib not found' unless have_library('z', 'inflate')
|
75
|
+
begin
|
76
|
+
fail 'Fail' unless have_library('gpr', 'gpr_now')
|
77
|
+
fail 'Fail' unless have_library('grpc', 'grpc_channel_destroy')
|
78
|
+
rescue
|
79
|
+
# Check to see if GRPC_ROOT is defined or available
|
80
|
+
grpc_root = check_grpc_root
|
83
81
|
|
84
|
-
|
82
|
+
# Stop if there is still no grpc_root
|
83
|
+
exit 1 if grpc_root.nil?
|
85
84
|
|
86
|
-
|
87
|
-
|
88
|
-
|
85
|
+
grpc_config = ENV['GRPC_CONFIG'] || 'opt'
|
86
|
+
if ENV.key?('GRPC_LIB_DIR')
|
87
|
+
grpc_lib_dir = File.join(grpc_root, ENV['GRPC_LIB_DIR'])
|
88
|
+
else
|
89
|
+
grpc_lib_dir = File.join(File.join(grpc_root, 'libs'), grpc_config)
|
90
|
+
end
|
91
|
+
unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a'))
|
92
|
+
print "Building internal gRPC\n"
|
93
|
+
system("make -C #{grpc_root} static_c CONFIG=#{grpc_config}")
|
94
|
+
end
|
95
|
+
$CFLAGS << ' -I' + File.join(grpc_root, 'include')
|
96
|
+
$LDFLAGS << ' -L' + grpc_lib_dir
|
97
|
+
raise 'gpr not found' unless have_library('gpr', 'gpr_now')
|
98
|
+
raise 'grpc not found' unless have_library('grpc', 'grpc_channel_destroy')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
$CFLAGS << ' -std=c99 '
|
89
103
|
$CFLAGS << ' -Wall '
|
104
|
+
$CFLAGS << ' -Wextra '
|
90
105
|
$CFLAGS << ' -pedantic '
|
106
|
+
$CFLAGS << ' -Werror '
|
91
107
|
|
92
|
-
$LDFLAGS << ' -lgrpc -lgpr -ldl'
|
93
|
-
|
94
|
-
crash('need grpc lib') unless have_library('grpc', 'grpc_channel_destroy')
|
95
|
-
have_library('grpc', 'grpc_channel_destroy')
|
96
|
-
crash('need gpr lib') unless have_library('gpr', 'gpr_now')
|
97
108
|
create_makefile('grpc/grpc')
|
data/ext/grpc/rb_byte_buffer.c
CHANGED
@@ -36,12 +36,13 @@
|
|
36
36
|
#include <ruby/ruby.h>
|
37
37
|
|
38
38
|
#include <grpc/grpc.h>
|
39
|
+
#include <grpc/byte_buffer_reader.h>
|
39
40
|
#include <grpc/support/slice.h>
|
40
41
|
#include "rb_grpc.h"
|
41
42
|
|
42
43
|
grpc_byte_buffer* grpc_rb_s_to_byte_buffer(char *string, size_t length) {
|
43
44
|
gpr_slice slice = gpr_slice_from_copied_buffer(string, length);
|
44
|
-
grpc_byte_buffer *buffer =
|
45
|
+
grpc_byte_buffer *buffer = grpc_raw_byte_buffer_create(&slice, 1);
|
45
46
|
gpr_slice_unref(slice);
|
46
47
|
return buffer;
|
47
48
|
}
|
@@ -50,7 +51,7 @@ VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer) {
|
|
50
51
|
size_t length = 0;
|
51
52
|
char *string = NULL;
|
52
53
|
size_t offset = 0;
|
53
|
-
grpc_byte_buffer_reader
|
54
|
+
grpc_byte_buffer_reader reader;
|
54
55
|
gpr_slice next;
|
55
56
|
if (buffer == NULL) {
|
56
57
|
return Qnil;
|
@@ -58,8 +59,8 @@ VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer) {
|
|
58
59
|
}
|
59
60
|
length = grpc_byte_buffer_length(buffer);
|
60
61
|
string = xmalloc(length + 1);
|
61
|
-
reader
|
62
|
-
while (grpc_byte_buffer_reader_next(reader, &next) != 0) {
|
62
|
+
grpc_byte_buffer_reader_init(&reader, buffer);
|
63
|
+
while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
|
63
64
|
memcpy(string + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
|
64
65
|
offset += GPR_SLICE_LENGTH(next);
|
65
66
|
}
|
data/ext/grpc/rb_call.c
CHANGED
@@ -142,8 +142,16 @@ grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
|
|
142
142
|
MEMZERO(&next_call, next_call_stack, 1);
|
143
143
|
TypedData_Get_Struct(self, grpc_completion_queue,
|
144
144
|
&grpc_rb_completion_queue_data_type, next_call.cq);
|
145
|
-
|
146
|
-
|
145
|
+
if (TYPE(timeout) == T_NIL) {
|
146
|
+
next_call.timeout = gpr_inf_future;
|
147
|
+
} else {
|
148
|
+
next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
|
149
|
+
}
|
150
|
+
if (TYPE(tag) == T_NIL) {
|
151
|
+
next_call.tag = NULL;
|
152
|
+
} else {
|
153
|
+
next_call.tag = ROBJECT(tag);
|
154
|
+
}
|
147
155
|
next_call.event.type = GRPC_QUEUE_TIMEOUT;
|
148
156
|
rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil,
|
149
157
|
(void *)&next_call, NULL, NULL);
|
data/ext/grpc/rb_server.c
CHANGED
@@ -68,8 +68,12 @@ static void grpc_rb_server_free(void *p) {
|
|
68
68
|
|
69
69
|
/* Deletes the wrapped object if the mark object is Qnil, which indicates
|
70
70
|
that no other object is the actual owner. */
|
71
|
+
/* grpc_server_shutdown does not exist. Change this to something that does
|
72
|
+
or delete it */
|
71
73
|
if (svr->wrapped != NULL && svr->mark == Qnil) {
|
72
|
-
grpc_server_shutdown(svr->wrapped);
|
74
|
+
// grpc_server_shutdown(svr->wrapped);
|
75
|
+
// Aborting to indicate a bug
|
76
|
+
abort();
|
73
77
|
grpc_server_destroy(svr->wrapped);
|
74
78
|
}
|
75
79
|
|
@@ -210,7 +214,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
|
|
210
214
|
VALUE result;
|
211
215
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
212
216
|
if (s->wrapped == NULL) {
|
213
|
-
rb_raise(rb_eRuntimeError, "
|
217
|
+
rb_raise(rb_eRuntimeError, "destroyed!");
|
214
218
|
return Qnil;
|
215
219
|
} else {
|
216
220
|
grpc_request_call_stack_init(&st);
|
@@ -259,21 +263,69 @@ static VALUE grpc_rb_server_start(VALUE self) {
|
|
259
263
|
grpc_rb_server *s = NULL;
|
260
264
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
261
265
|
if (s->wrapped == NULL) {
|
262
|
-
rb_raise(rb_eRuntimeError, "
|
266
|
+
rb_raise(rb_eRuntimeError, "destroyed!");
|
263
267
|
} else {
|
264
268
|
grpc_server_start(s->wrapped);
|
265
269
|
}
|
266
270
|
return Qnil;
|
267
271
|
}
|
268
272
|
|
269
|
-
|
273
|
+
/*
|
274
|
+
call-seq:
|
275
|
+
cq = CompletionQueue.new
|
276
|
+
server = Server.new(cq, {'arg1': 'value1'})
|
277
|
+
... // do stuff with server
|
278
|
+
...
|
279
|
+
... // to shutdown the server
|
280
|
+
server.destroy(cq)
|
281
|
+
|
282
|
+
... // to shutdown the server with a timeout
|
283
|
+
server.destroy(cq, timeout)
|
284
|
+
|
285
|
+
Destroys server instances. */
|
286
|
+
static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) {
|
287
|
+
VALUE cqueue = Qnil;
|
288
|
+
VALUE timeout = Qnil;
|
289
|
+
grpc_completion_queue *cq = NULL;
|
290
|
+
grpc_event ev;
|
270
291
|
grpc_rb_server *s = NULL;
|
292
|
+
|
293
|
+
/* "11" == 1 mandatory args, 1 (timeout) is optional */
|
294
|
+
rb_scan_args(argc, argv, "11", &cqueue, &timeout);
|
295
|
+
cq = grpc_rb_get_wrapped_completion_queue(cqueue);
|
271
296
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
297
|
+
|
272
298
|
if (s->wrapped != NULL) {
|
273
|
-
|
299
|
+
grpc_server_shutdown_and_notify(s->wrapped, cq, NULL);
|
300
|
+
ev = grpc_rb_completion_queue_pluck_event(cqueue, Qnil, timeout);
|
301
|
+
|
302
|
+
if (!ev.success) {
|
303
|
+
rb_warn("server shutdown failed, there will be a LEAKED object warning");
|
304
|
+
return Qnil;
|
305
|
+
/*
|
306
|
+
TODO: renable the rb_raise below.
|
307
|
+
|
308
|
+
At the moment if the timeout is INFINITE_FUTURE as recommended, the
|
309
|
+
pluck blocks forever, even though
|
310
|
+
|
311
|
+
the outstanding server_request_calls correctly fail on the other
|
312
|
+
thread that they are running on.
|
313
|
+
|
314
|
+
it's almost as if calls that fail on the other thread do not get
|
315
|
+
cleaned up by shutdown request, even though it caused htem to
|
316
|
+
terminate.
|
317
|
+
|
318
|
+
rb_raise(rb_eRuntimeError, "grpc server shutdown did not succeed");
|
319
|
+
return Qnil;
|
320
|
+
|
321
|
+
The workaround is just to use a timeout and return without really
|
322
|
+
shutting down the server, and rely on the grpc core garbage collection
|
323
|
+
it down as a 'LEAKED OBJECT'.
|
324
|
+
|
325
|
+
*/
|
326
|
+
}
|
274
327
|
grpc_server_destroy(s->wrapped);
|
275
328
|
s->wrapped = NULL;
|
276
|
-
s->mark = Qnil;
|
277
329
|
}
|
278
330
|
return Qnil;
|
279
331
|
}
|
@@ -302,7 +354,7 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
|
|
302
354
|
|
303
355
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
304
356
|
if (s->wrapped == NULL) {
|
305
|
-
rb_raise(rb_eRuntimeError, "
|
357
|
+
rb_raise(rb_eRuntimeError, "destroyed!");
|
306
358
|
return Qnil;
|
307
359
|
} else if (rb_creds == Qnil) {
|
308
360
|
recvd_port = grpc_server_add_http2_port(s->wrapped, StringValueCStr(port));
|
@@ -315,7 +367,7 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
|
|
315
367
|
creds = grpc_rb_get_wrapped_server_credentials(rb_creds);
|
316
368
|
recvd_port =
|
317
369
|
grpc_server_add_secure_http2_port(s->wrapped, StringValueCStr(port),
|
318
|
-
|
370
|
+
creds);
|
319
371
|
if (recvd_port == 0) {
|
320
372
|
rb_raise(rb_eRuntimeError,
|
321
373
|
"could not add secure port %s to server, not sure why",
|
@@ -341,7 +393,7 @@ void Init_grpc_server() {
|
|
341
393
|
rb_define_method(grpc_rb_cServer, "request_call",
|
342
394
|
grpc_rb_server_request_call, 3);
|
343
395
|
rb_define_method(grpc_rb_cServer, "start", grpc_rb_server_start, 0);
|
344
|
-
rb_define_method(grpc_rb_cServer, "destroy", grpc_rb_server_destroy,
|
396
|
+
rb_define_method(grpc_rb_cServer, "destroy", grpc_rb_server_destroy, -1);
|
345
397
|
rb_define_alias(grpc_rb_cServer, "close", "destroy");
|
346
398
|
rb_define_method(grpc_rb_cServer, "add_http2_port",
|
347
399
|
grpc_rb_server_add_http2_port,
|
data/grpc.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.license = 'BSD-3-Clause'
|
15
15
|
|
16
16
|
s.required_ruby_version = '>= 2.0.0'
|
17
|
-
s.requirements << 'libgrpc ~> 0.
|
17
|
+
s.requirements << 'libgrpc ~> 0.10.0 needs to be installed'
|
18
18
|
|
19
19
|
s.files = `git ls-files`.split("\n")
|
20
20
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
@@ -39,6 +39,7 @@ class Struct
|
|
39
39
|
return nil if status.nil?
|
40
40
|
fail GRPC::Cancelled if status.code == GRPC::Core::StatusCodes::CANCELLED
|
41
41
|
if status.code != GRPC::Core::StatusCodes::OK
|
42
|
+
GRPC.logger.debug("Failing with status #{status}")
|
42
43
|
# raise BadStatus, propagating the metadata if present.
|
43
44
|
md = status.metadata
|
44
45
|
with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }]
|
@@ -54,7 +55,6 @@ module GRPC
|
|
54
55
|
# The ActiveCall class provides simple methods for sending marshallable
|
55
56
|
# data to a call
|
56
57
|
class ActiveCall
|
57
|
-
include Core::StatusCodes
|
58
58
|
include Core::TimeConsts
|
59
59
|
include Core::CallOps
|
60
60
|
extend Forwardable
|
@@ -120,6 +120,7 @@ module GRPC
|
|
120
120
|
@started = started
|
121
121
|
@unmarshal = unmarshal
|
122
122
|
@metadata_tag = metadata_tag
|
123
|
+
@op_notifier = nil
|
123
124
|
end
|
124
125
|
|
125
126
|
# output_metadata are provides access to hash that can be used to
|
@@ -128,6 +129,11 @@ module GRPC
|
|
128
129
|
@output_metadata ||= {}
|
129
130
|
end
|
130
131
|
|
132
|
+
# cancelled indicates if the call was cancelled
|
133
|
+
def cancelled
|
134
|
+
!@call.status.nil? && @call.status.code == Core::StatusCodes::CANCELLED
|
135
|
+
end
|
136
|
+
|
131
137
|
# multi_req_view provides a restricted view of this ActiveCall for use
|
132
138
|
# in a server client-streaming handler.
|
133
139
|
def multi_req_view
|
@@ -143,6 +149,7 @@ module GRPC
|
|
143
149
|
# operation provides a restricted view of this ActiveCall for use as
|
144
150
|
# a Operation.
|
145
151
|
def operation
|
152
|
+
@op_notifier = Notifier.new
|
146
153
|
Operation.new(self)
|
147
154
|
end
|
148
155
|
|
@@ -161,6 +168,8 @@ module GRPC
|
|
161
168
|
ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished
|
162
169
|
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
|
163
170
|
return unless assert_finished
|
171
|
+
@call.status = batch_result.status
|
172
|
+
op_is_done
|
164
173
|
batch_result.check_status
|
165
174
|
end
|
166
175
|
|
@@ -177,6 +186,8 @@ module GRPC
|
|
177
186
|
@call.metadata.merge!(batch_result.status.metadata)
|
178
187
|
end
|
179
188
|
end
|
189
|
+
@call.status = batch_result.status
|
190
|
+
op_is_done
|
180
191
|
batch_result.check_status
|
181
192
|
end
|
182
193
|
|
@@ -408,10 +419,7 @@ module GRPC
|
|
408
419
|
def bidi_streamer(requests, **kw, &blk)
|
409
420
|
start_call(**kw) unless @started
|
410
421
|
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline)
|
411
|
-
bd.run_on_client(requests, &blk)
|
412
|
-
rescue GRPC::Core::CallError => e
|
413
|
-
finished # checks for Cancelled
|
414
|
-
raise e
|
422
|
+
bd.run_on_client(requests, @op_notifier, &blk)
|
415
423
|
end
|
416
424
|
|
417
425
|
# run_server_bidi orchestrates a BiDi stream processing on a server.
|
@@ -430,6 +438,19 @@ module GRPC
|
|
430
438
|
bd.run_on_server(gen_each_reply)
|
431
439
|
end
|
432
440
|
|
441
|
+
# Waits till an operation completes
|
442
|
+
def wait
|
443
|
+
return if @op_notifier.nil?
|
444
|
+
GRPC.logger.debug("active_call.wait: on #{@op_notifier}")
|
445
|
+
@op_notifier.wait
|
446
|
+
end
|
447
|
+
|
448
|
+
# Signals that an operation is done
|
449
|
+
def op_is_done
|
450
|
+
return if @op_notifier.nil?
|
451
|
+
@op_notifier.notify(self)
|
452
|
+
end
|
453
|
+
|
433
454
|
private
|
434
455
|
|
435
456
|
# Starts the call if not already started
|
@@ -464,6 +485,6 @@ module GRPC
|
|
464
485
|
# Operation limits access to an ActiveCall's methods for use as
|
465
486
|
# a Operation on the client.
|
466
487
|
Operation = view_class(:cancel, :cancelled, :deadline, :execute,
|
467
|
-
:metadata, :status, :start_call)
|
488
|
+
:metadata, :status, :start_call, :wait)
|
468
489
|
end
|
469
490
|
end
|
@@ -66,6 +66,7 @@ module GRPC
|
|
66
66
|
@cq = q
|
67
67
|
@deadline = deadline
|
68
68
|
@marshal = marshal
|
69
|
+
@op_notifier = nil # signals completion on clients
|
69
70
|
@readq = Queue.new
|
70
71
|
@unmarshal = unmarshal
|
71
72
|
end
|
@@ -76,13 +77,13 @@ module GRPC
|
|
76
77
|
# block that can be invoked with each response.
|
77
78
|
#
|
78
79
|
# @param requests the Enumerable of requests to send
|
80
|
+
# @op_notifier a Notifier used to signal completion
|
79
81
|
# @return an Enumerator of requests to yield
|
80
|
-
def run_on_client(requests, &blk)
|
81
|
-
@
|
82
|
+
def run_on_client(requests, op_notifier, &blk)
|
83
|
+
@op_notifier = op_notifier
|
84
|
+
@enq_th = Thread.new { write_loop(requests) }
|
82
85
|
@loop_th = start_read_loop
|
83
|
-
|
84
|
-
return replies if blk.nil?
|
85
|
-
replies.each { |r| blk.call(r) }
|
86
|
+
each_queued_msg(&blk)
|
86
87
|
end
|
87
88
|
|
88
89
|
# Begins orchestration of the Bidi stream for a server generating replies.
|
@@ -98,8 +99,8 @@ module GRPC
|
|
98
99
|
# @param gen_each_reply [Proc] generates the BiDi stream replies.
|
99
100
|
def run_on_server(gen_each_reply)
|
100
101
|
replys = gen_each_reply.call(each_queued_msg)
|
101
|
-
@enq_th = start_write_loop(replys, is_client: false)
|
102
102
|
@loop_th = start_read_loop
|
103
|
+
write_loop(replys, is_client: false)
|
103
104
|
end
|
104
105
|
|
105
106
|
private
|
@@ -107,6 +108,13 @@ module GRPC
|
|
107
108
|
END_OF_READS = :end_of_reads
|
108
109
|
END_OF_WRITES = :end_of_writes
|
109
110
|
|
111
|
+
# signals that bidi operation is complete
|
112
|
+
def notify_done
|
113
|
+
return unless @op_notifier
|
114
|
+
GRPC.logger.debug("bidi-notify-done: notifying #{@op_notifier}")
|
115
|
+
@op_notifier.notify(self)
|
116
|
+
end
|
117
|
+
|
110
118
|
# each_queued_msg yields each message on this instances readq
|
111
119
|
#
|
112
120
|
# - messages are added to the readq by #read_loop
|
@@ -115,7 +123,7 @@ module GRPC
|
|
115
123
|
return enum_for(:each_queued_msg) unless block_given?
|
116
124
|
count = 0
|
117
125
|
loop do
|
118
|
-
GRPC.logger.debug("each_queued_msg:
|
126
|
+
GRPC.logger.debug("each_queued_msg: waiting##{count}")
|
119
127
|
count += 1
|
120
128
|
req = @readq.pop
|
121
129
|
GRPC.logger.debug("each_queued_msg: req = #{req}")
|
@@ -123,70 +131,70 @@ module GRPC
|
|
123
131
|
break if req.equal?(END_OF_READS)
|
124
132
|
yield req
|
125
133
|
end
|
126
|
-
@enq_th.join if @enq_th.alive?
|
127
134
|
end
|
128
135
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
payload = @marshal.call(req)
|
140
|
-
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
|
141
|
-
SEND_MESSAGE => payload)
|
142
|
-
end
|
143
|
-
if is_client
|
144
|
-
GRPC.logger.debug("bidi-write-loop: sent #{count}, waiting")
|
145
|
-
batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
|
146
|
-
SEND_CLOSE_FROM_CLIENT => nil,
|
147
|
-
RECV_STATUS_ON_CLIENT => nil)
|
148
|
-
batch_result.check_status
|
149
|
-
end
|
150
|
-
rescue StandardError => e
|
151
|
-
GRPC.logger.warn('bidi-write_loop: failed')
|
152
|
-
GRPC.logger.warn(e)
|
153
|
-
raise e
|
154
|
-
end
|
136
|
+
def write_loop(requests, is_client: true)
|
137
|
+
GRPC.logger.debug('bidi-write-loop: starting')
|
138
|
+
write_tag = Object.new
|
139
|
+
count = 0
|
140
|
+
requests.each do |req|
|
141
|
+
GRPC.logger.debug("bidi-write-loop: #{count}")
|
142
|
+
count += 1
|
143
|
+
payload = @marshal.call(req)
|
144
|
+
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
|
145
|
+
SEND_MESSAGE => payload)
|
155
146
|
end
|
147
|
+
GRPC.logger.debug("bidi-write-loop: #{count} writes done")
|
148
|
+
if is_client
|
149
|
+
GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
|
150
|
+
batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
|
151
|
+
SEND_CLOSE_FROM_CLIENT => nil,
|
152
|
+
RECV_STATUS_ON_CLIENT => nil)
|
153
|
+
@call.status = batch_result.status
|
154
|
+
batch_result.check_status
|
155
|
+
GRPC.logger.debug("bidi-write-loop: done status #{@call.status}")
|
156
|
+
notify_done
|
157
|
+
end
|
158
|
+
GRPC.logger.debug('bidi-write-loop: finished')
|
159
|
+
rescue StandardError => e
|
160
|
+
GRPC.logger.warn('bidi-write-loop: failed')
|
161
|
+
GRPC.logger.warn(e)
|
162
|
+
notify_done
|
163
|
+
raise e
|
156
164
|
end
|
157
165
|
|
158
166
|
# starts the read loop
|
159
167
|
def start_read_loop
|
160
168
|
Thread.new do
|
169
|
+
GRPC.logger.debug('bidi-read-loop: starting')
|
161
170
|
begin
|
162
171
|
read_tag = Object.new
|
163
172
|
count = 0
|
164
|
-
|
165
173
|
# queue the initial read before beginning the loop
|
166
174
|
loop do
|
167
|
-
GRPC.logger.debug("bidi-
|
175
|
+
GRPC.logger.debug("bidi-read-loop: #{count}")
|
168
176
|
count += 1
|
169
177
|
# TODO: ensure metadata is read if available, currently it's not
|
170
178
|
batch_result = @call.run_batch(@cq, read_tag, INFINITE_FUTURE,
|
171
179
|
RECV_MESSAGE => nil)
|
172
180
|
# handle the next message
|
173
181
|
if batch_result.message.nil?
|
182
|
+
GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
|
174
183
|
@readq.push(END_OF_READS)
|
175
184
|
GRPC.logger.debug('bidi-read-loop: done reading!')
|
176
185
|
break
|
177
186
|
end
|
178
187
|
|
179
188
|
# push the latest read onto the queue and continue reading
|
180
|
-
GRPC.logger.debug("received req: #{batch_result.message}")
|
181
189
|
res = @unmarshal.call(batch_result.message)
|
182
190
|
@readq.push(res)
|
183
191
|
end
|
184
|
-
|
185
192
|
rescue StandardError => e
|
186
|
-
GRPC.logger.warn('bidi:
|
193
|
+
GRPC.logger.warn('bidi: read-loop failed')
|
187
194
|
GRPC.logger.warn(e)
|
188
195
|
@readq.push(e) # let each_queued_msg terminate with this error
|
189
196
|
end
|
197
|
+
GRPC.logger.debug('bidi-read-loop: finished')
|
190
198
|
end
|
191
199
|
end
|
192
200
|
end
|
@@ -137,6 +137,7 @@ module GRPC
|
|
137
137
|
|
138
138
|
def send_status(active_client, code, details, **kw)
|
139
139
|
details = 'Not sure why' if details.nil?
|
140
|
+
GRPC.logger.debug("Sending status #{code}:#{details}")
|
140
141
|
active_client.send_status(code, details, code == OK, **kw)
|
141
142
|
rescue StandardError => e
|
142
143
|
GRPC.logger.warn("Could not send status #{code}:#{details}")
|
@@ -278,7 +278,9 @@ module GRPC
|
|
278
278
|
@stopped = true
|
279
279
|
end
|
280
280
|
@pool.stop
|
281
|
-
@
|
281
|
+
deadline = from_relative_time(@poll_period)
|
282
|
+
|
283
|
+
@server.close(@cq, deadline)
|
282
284
|
end
|
283
285
|
|
284
286
|
# determines if the server has been stopped
|
@@ -410,17 +412,18 @@ module GRPC
|
|
410
412
|
# handles calls to the server
|
411
413
|
def loop_handle_server_calls
|
412
414
|
fail 'not running' unless @running
|
413
|
-
|
415
|
+
loop_tag = Object.new
|
414
416
|
until stopped?
|
415
417
|
deadline = from_relative_time(@poll_period)
|
416
418
|
begin
|
417
|
-
an_rpc = @server.request_call(@cq,
|
419
|
+
an_rpc = @server.request_call(@cq, loop_tag, deadline)
|
420
|
+
c = new_active_server_call(an_rpc)
|
418
421
|
rescue Core::CallError, RuntimeError => e
|
419
|
-
#
|
422
|
+
# these might happen for various reasonse. The correct behaviour of
|
423
|
+
# the server is to log them and continue.
|
420
424
|
GRPC.logger.warn("server call failed: #{e}")
|
421
425
|
next
|
422
426
|
end
|
423
|
-
c = new_active_server_call(an_rpc)
|
424
427
|
unless c.nil?
|
425
428
|
mth = an_rpc.method.to_sym
|
426
429
|
@pool.schedule(c) do |call|
|
data/lib/grpc/logconfig.rb
CHANGED
@@ -38,6 +38,6 @@ Logging.logger.root.appenders = Logging.appenders.stdout
|
|
38
38
|
Logging.logger.root.level = :info
|
39
39
|
|
40
40
|
# TODO: provide command-line configuration for logging
|
41
|
-
Logging.logger['GRPC'].level = :
|
41
|
+
Logging.logger['GRPC'].level = :info
|
42
42
|
Logging.logger['GRPC::ActiveCall'].level = :info
|
43
43
|
Logging.logger['GRPC::BidiCall'].level = :info
|
data/lib/grpc/version.rb
CHANGED
data/spec/client_server_spec.rb
CHANGED
@@ -42,11 +42,8 @@ shared_context 'setup: tags' do
|
|
42
42
|
let(:sent_message) { 'sent message' }
|
43
43
|
let(:reply_text) { 'the reply' }
|
44
44
|
before(:example) do
|
45
|
-
@
|
46
|
-
@client_finished_tag = Object.new
|
47
|
-
@client_metadata_tag = Object.new
|
45
|
+
@client_tag = Object.new
|
48
46
|
@server_tag = Object.new
|
49
|
-
@tag = Object.new
|
50
47
|
end
|
51
48
|
|
52
49
|
def deadline
|
@@ -74,6 +71,12 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
74
71
|
|
75
72
|
it 'servers receive requests from clients and can respond' do
|
76
73
|
call = new_client_call
|
74
|
+
server_call = nil
|
75
|
+
|
76
|
+
server_thread = Thread.new do
|
77
|
+
server_call = server_allows_client_to_proceed
|
78
|
+
end
|
79
|
+
|
77
80
|
client_ops = {
|
78
81
|
CallOps::SEND_INITIAL_METADATA => {},
|
79
82
|
CallOps::SEND_MESSAGE => sent_message
|
@@ -84,7 +87,7 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
84
87
|
expect(batch_result.send_message).to be true
|
85
88
|
|
86
89
|
# confirm the server can read the inbound message
|
87
|
-
|
90
|
+
server_thread.join
|
88
91
|
server_ops = {
|
89
92
|
CallOps::RECV_MESSAGE => nil
|
90
93
|
}
|
@@ -95,6 +98,12 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
95
98
|
|
96
99
|
it 'responses written by servers are received by the client' do
|
97
100
|
call = new_client_call
|
101
|
+
server_call = nil
|
102
|
+
|
103
|
+
server_thread = Thread.new do
|
104
|
+
server_call = server_allows_client_to_proceed
|
105
|
+
end
|
106
|
+
|
98
107
|
client_ops = {
|
99
108
|
CallOps::SEND_INITIAL_METADATA => {},
|
100
109
|
CallOps::SEND_MESSAGE => sent_message
|
@@ -105,7 +114,7 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
105
114
|
expect(batch_result.send_message).to be true
|
106
115
|
|
107
116
|
# confirm the server can read the inbound message
|
108
|
-
|
117
|
+
server_thread.join
|
109
118
|
server_ops = {
|
110
119
|
CallOps::RECV_MESSAGE => nil,
|
111
120
|
CallOps::SEND_MESSAGE => reply_text
|
@@ -118,6 +127,12 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
118
127
|
|
119
128
|
it 'servers can ignore a client write and send a status' do
|
120
129
|
call = new_client_call
|
130
|
+
server_call = nil
|
131
|
+
|
132
|
+
server_thread = Thread.new do
|
133
|
+
server_call = server_allows_client_to_proceed
|
134
|
+
end
|
135
|
+
|
121
136
|
client_ops = {
|
122
137
|
CallOps::SEND_INITIAL_METADATA => {},
|
123
138
|
CallOps::SEND_MESSAGE => sent_message
|
@@ -129,7 +144,7 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
129
144
|
|
130
145
|
# confirm the server can read the inbound message
|
131
146
|
the_status = Struct::Status.new(StatusCodes::OK, 'OK')
|
132
|
-
|
147
|
+
server_thread.join
|
133
148
|
server_ops = {
|
134
149
|
CallOps::SEND_STATUS_FROM_SERVER => the_status
|
135
150
|
}
|
@@ -141,6 +156,12 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
141
156
|
|
142
157
|
it 'completes calls by sending status to client and server' do
|
143
158
|
call = new_client_call
|
159
|
+
server_call = nil
|
160
|
+
|
161
|
+
server_thread = Thread.new do
|
162
|
+
server_call = server_allows_client_to_proceed
|
163
|
+
end
|
164
|
+
|
144
165
|
client_ops = {
|
145
166
|
CallOps::SEND_INITIAL_METADATA => {},
|
146
167
|
CallOps::SEND_MESSAGE => sent_message
|
@@ -152,7 +173,7 @@ shared_examples 'basic GRPC message delivery is OK' do
|
|
152
173
|
|
153
174
|
# confirm the server can read the inbound message and respond
|
154
175
|
the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
|
155
|
-
|
176
|
+
server_thread.join
|
156
177
|
server_ops = {
|
157
178
|
CallOps::RECV_MESSAGE => nil,
|
158
179
|
CallOps::SEND_MESSAGE => reply_text,
|
@@ -221,6 +242,11 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
221
242
|
|
222
243
|
it 'sends all the metadata pairs when keys and values are valid' do
|
223
244
|
@valid_metadata.each do |md|
|
245
|
+
recvd_rpc = nil
|
246
|
+
rcv_thread = Thread.new do
|
247
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
248
|
+
end
|
249
|
+
|
224
250
|
call = new_client_call
|
225
251
|
client_ops = {
|
226
252
|
CallOps::SEND_INITIAL_METADATA => md
|
@@ -230,7 +256,7 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
230
256
|
expect(batch_result.send_metadata).to be true
|
231
257
|
|
232
258
|
# confirm the server can receive the client metadata
|
233
|
-
|
259
|
+
rcv_thread.join
|
234
260
|
expect(recvd_rpc).to_not eq nil
|
235
261
|
recvd_md = recvd_rpc.metadata
|
236
262
|
replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
|
@@ -257,6 +283,11 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
257
283
|
|
258
284
|
it 'raises an exception if a metadata key is invalid' do
|
259
285
|
@bad_keys.each do |md|
|
286
|
+
recvd_rpc = nil
|
287
|
+
rcv_thread = Thread.new do
|
288
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
289
|
+
end
|
290
|
+
|
260
291
|
call = new_client_call
|
261
292
|
# client signals that it's done sending metadata to allow server to
|
262
293
|
# respond
|
@@ -266,7 +297,7 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
266
297
|
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
267
298
|
|
268
299
|
# server gets the invocation
|
269
|
-
|
300
|
+
rcv_thread.join
|
270
301
|
expect(recvd_rpc).to_not eq nil
|
271
302
|
server_ops = {
|
272
303
|
CallOps::SEND_INITIAL_METADATA => md
|
@@ -280,6 +311,11 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
280
311
|
end
|
281
312
|
|
282
313
|
it 'sends an empty hash if no metadata is added' do
|
314
|
+
recvd_rpc = nil
|
315
|
+
rcv_thread = Thread.new do
|
316
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
317
|
+
end
|
318
|
+
|
283
319
|
call = new_client_call
|
284
320
|
# client signals that it's done sending metadata to allow server to
|
285
321
|
# respond
|
@@ -289,7 +325,7 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
289
325
|
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
290
326
|
|
291
327
|
# server gets the invocation but sends no metadata back
|
292
|
-
|
328
|
+
rcv_thread.join
|
293
329
|
expect(recvd_rpc).to_not eq nil
|
294
330
|
server_call = recvd_rpc.call
|
295
331
|
server_ops = {
|
@@ -308,6 +344,11 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
308
344
|
|
309
345
|
it 'sends all the pairs when keys and values are valid' do
|
310
346
|
@valid_metadata.each do |md|
|
347
|
+
recvd_rpc = nil
|
348
|
+
rcv_thread = Thread.new do
|
349
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
350
|
+
end
|
351
|
+
|
311
352
|
call = new_client_call
|
312
353
|
# client signals that it's done sending metadata to allow server to
|
313
354
|
# respond
|
@@ -317,7 +358,7 @@ shared_examples 'GRPC metadata delivery works OK' do
|
|
317
358
|
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
318
359
|
|
319
360
|
# server gets the invocation but sends no metadata back
|
320
|
-
|
361
|
+
rcv_thread.join
|
321
362
|
expect(recvd_rpc).to_not eq nil
|
322
363
|
server_call = recvd_rpc.call
|
323
364
|
server_ops = {
|
@@ -351,7 +392,7 @@ describe 'the http client/server' do
|
|
351
392
|
|
352
393
|
after(:example) do
|
353
394
|
@ch.close
|
354
|
-
@server.close
|
395
|
+
@server.close(@server_queue, deadline)
|
355
396
|
end
|
356
397
|
|
357
398
|
it_behaves_like 'basic GRPC message delivery is OK' do
|
@@ -377,7 +418,7 @@ describe 'the secure http client/server' do
|
|
377
418
|
end
|
378
419
|
|
379
420
|
after(:example) do
|
380
|
-
@server.close
|
421
|
+
@server.close(@server_queue, deadline)
|
381
422
|
end
|
382
423
|
|
383
424
|
it_behaves_like 'basic GRPC message delivery is OK' do
|
@@ -54,6 +54,7 @@ describe 'ClientStub' do
|
|
54
54
|
before(:each) do
|
55
55
|
Thread.abort_on_exception = true
|
56
56
|
@server = nil
|
57
|
+
@server_queue = nil
|
57
58
|
@method = 'an_rpc_method'
|
58
59
|
@pass = OK
|
59
60
|
@fail = INTERNAL
|
@@ -61,7 +62,7 @@ describe 'ClientStub' do
|
|
61
62
|
end
|
62
63
|
|
63
64
|
after(:each) do
|
64
|
-
@server.close unless @
|
65
|
+
@server.close(@server_queue) unless @server_queue.nil?
|
65
66
|
end
|
66
67
|
|
67
68
|
describe '#new' do
|
@@ -136,10 +136,6 @@ describe GRPC::RpcServer do
|
|
136
136
|
@ch = GRPC::Core::Channel.new(@host, nil)
|
137
137
|
end
|
138
138
|
|
139
|
-
after(:each) do
|
140
|
-
@server.close
|
141
|
-
end
|
142
|
-
|
143
139
|
describe '#new' do
|
144
140
|
it 'can be created with just some args' do
|
145
141
|
opts = { a_channel_arg: 'an_arg' }
|
@@ -344,10 +340,6 @@ describe GRPC::RpcServer do
|
|
344
340
|
@srv = RpcServer.new(**server_opts)
|
345
341
|
end
|
346
342
|
|
347
|
-
after(:each) do
|
348
|
-
@srv.stop
|
349
|
-
end
|
350
|
-
|
351
343
|
it 'should return NOT_FOUND status on unknown methods', server: true do
|
352
344
|
@srv.handle(EchoService)
|
353
345
|
t = Thread.new { @srv.run }
|
@@ -527,10 +519,6 @@ describe GRPC::RpcServer do
|
|
527
519
|
@srv = RpcServer.new(**server_opts)
|
528
520
|
end
|
529
521
|
|
530
|
-
after(:each) do
|
531
|
-
@srv.stop
|
532
|
-
end
|
533
|
-
|
534
522
|
it 'should send connect metadata to the client', server: true do
|
535
523
|
service = EchoService.new
|
536
524
|
@srv.handle(service)
|
data/spec/server_spec.rb
CHANGED
@@ -54,7 +54,7 @@ describe Server do
|
|
54
54
|
|
55
55
|
it 'fails if the server is closed' do
|
56
56
|
s = Server.new(@cq, nil)
|
57
|
-
s.close
|
57
|
+
s.close(@cq)
|
58
58
|
expect { s.start }.to raise_error(RuntimeError)
|
59
59
|
end
|
60
60
|
end
|
@@ -62,19 +62,19 @@ describe Server do
|
|
62
62
|
describe '#destroy' do
|
63
63
|
it 'destroys a server ok' do
|
64
64
|
s = start_a_server
|
65
|
-
blk = proc { s.destroy }
|
65
|
+
blk = proc { s.destroy(@cq) }
|
66
66
|
expect(&blk).to_not raise_error
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'can be called more than once without error' do
|
70
70
|
s = start_a_server
|
71
71
|
begin
|
72
|
-
blk = proc { s.destroy }
|
72
|
+
blk = proc { s.destroy(@cq) }
|
73
73
|
expect(&blk).to_not raise_error
|
74
74
|
blk.call
|
75
75
|
expect(&blk).to_not raise_error
|
76
76
|
ensure
|
77
|
-
s.close
|
77
|
+
s.close(@cq)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
@@ -83,16 +83,16 @@ describe Server do
|
|
83
83
|
it 'closes a server ok' do
|
84
84
|
s = start_a_server
|
85
85
|
begin
|
86
|
-
blk = proc { s.close }
|
86
|
+
blk = proc { s.close(@cq) }
|
87
87
|
expect(&blk).to_not raise_error
|
88
88
|
ensure
|
89
|
-
s.close
|
89
|
+
s.close(@cq)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'can be called more than once without error' do
|
94
94
|
s = start_a_server
|
95
|
-
blk = proc { s.close }
|
95
|
+
blk = proc { s.close(@cq) }
|
96
96
|
expect(&blk).to_not raise_error
|
97
97
|
blk.call
|
98
98
|
expect(&blk).to_not raise_error
|
@@ -105,14 +105,14 @@ describe Server do
|
|
105
105
|
blk = proc do
|
106
106
|
s = Server.new(@cq, nil)
|
107
107
|
s.add_http2_port('localhost:0')
|
108
|
-
s.close
|
108
|
+
s.close(@cq)
|
109
109
|
end
|
110
110
|
expect(&blk).to_not raise_error
|
111
111
|
end
|
112
112
|
|
113
113
|
it 'fails if the server is closed' do
|
114
114
|
s = Server.new(@cq, nil)
|
115
|
-
s.close
|
115
|
+
s.close(@cq)
|
116
116
|
expect { s.add_http2_port('localhost:0') }.to raise_error(RuntimeError)
|
117
117
|
end
|
118
118
|
end
|
@@ -123,14 +123,14 @@ describe Server do
|
|
123
123
|
blk = proc do
|
124
124
|
s = Server.new(@cq, nil)
|
125
125
|
s.add_http2_port('localhost:0', cert)
|
126
|
-
s.close
|
126
|
+
s.close(@cq)
|
127
127
|
end
|
128
128
|
expect(&blk).to_not raise_error
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'fails if the server is closed' do
|
132
132
|
s = Server.new(@cq, nil)
|
133
|
-
s.close
|
133
|
+
s.close(@cq)
|
134
134
|
blk = proc { s.add_http2_port('localhost:0', cert) }
|
135
135
|
expect(&blk).to raise_error(RuntimeError)
|
136
136
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gRPC Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -259,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
259
259
|
- !ruby/object:Gem::Version
|
260
260
|
version: '0'
|
261
261
|
requirements:
|
262
|
-
- libgrpc ~> 0.
|
262
|
+
- libgrpc ~> 0.10.0 needs to be installed
|
263
263
|
rubyforge_project:
|
264
264
|
rubygems_version: 2.4.3
|
265
265
|
signing_key:
|