grpc 0.6.0 → 0.6.1
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 +1 -0
- data/.rubocop_todo.yml +12 -20
- data/CHANGELOG.md +11 -0
- data/Rakefile +1 -0
- data/bin/apis/pubsub_demo.rb +3 -6
- data/bin/interop/interop_client.rb +43 -3
- data/bin/interop/interop_server.rb +1 -1
- data/bin/math_server.rb +1 -1
- data/bin/noproto_server.rb +1 -1
- data/ext/grpc/rb_byte_buffer.c +15 -189
- data/ext/grpc/rb_byte_buffer.h +4 -12
- data/ext/grpc/rb_call.c +514 -307
- data/ext/grpc/rb_call.h +4 -4
- data/ext/grpc/rb_channel.c +58 -34
- data/ext/grpc/rb_channel.h +0 -3
- data/ext/grpc/rb_channel_args.c +13 -4
- data/ext/grpc/rb_completion_queue.c +50 -23
- data/ext/grpc/rb_completion_queue.h +7 -3
- data/ext/grpc/rb_credentials.c +40 -28
- data/ext/grpc/rb_credentials.h +0 -4
- data/ext/grpc/rb_grpc.c +86 -67
- data/ext/grpc/rb_grpc.h +20 -10
- data/ext/grpc/rb_server.c +119 -26
- data/ext/grpc/rb_server.h +0 -4
- data/ext/grpc/rb_server_credentials.c +29 -16
- data/ext/grpc/rb_server_credentials.h +0 -4
- data/grpc.gemspec +11 -8
- data/lib/grpc.rb +1 -1
- data/lib/grpc/errors.rb +8 -7
- data/lib/grpc/generic/active_call.rb +104 -171
- data/lib/grpc/generic/bidi_call.rb +32 -60
- data/lib/grpc/generic/client_stub.rb +42 -31
- data/lib/grpc/generic/rpc_desc.rb +7 -12
- data/lib/grpc/generic/rpc_server.rb +253 -170
- data/lib/grpc/{core/event.rb → notifier.rb} +25 -9
- data/lib/grpc/version.rb +1 -1
- data/spec/call_spec.rb +23 -40
- data/spec/channel_spec.rb +11 -20
- data/spec/client_server_spec.rb +193 -175
- data/spec/credentials_spec.rb +2 -2
- data/spec/generic/active_call_spec.rb +59 -85
- data/spec/generic/client_stub_spec.rb +46 -64
- data/spec/generic/rpc_desc_spec.rb +50 -80
- data/spec/generic/rpc_server_pool_spec.rb +2 -3
- data/spec/generic/rpc_server_spec.rb +158 -29
- data/spec/server_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -4
- metadata +27 -37
- data/ext/grpc/rb_event.c +0 -361
- data/ext/grpc/rb_event.h +0 -53
- data/ext/grpc/rb_metadata.c +0 -215
- data/ext/grpc/rb_metadata.h +0 -53
- data/spec/alloc_spec.rb +0 -44
- data/spec/byte_buffer_spec.rb +0 -67
- data/spec/event_spec.rb +0 -53
- data/spec/metadata_spec.rb +0 -64
data/ext/grpc/rb_server.h
CHANGED
@@ -40,6 +40,10 @@
|
|
40
40
|
|
41
41
|
#include "rb_grpc.h"
|
42
42
|
|
43
|
+
/* grpc_rb_cServerCredentials is the ruby class that proxies
|
44
|
+
grpc_server_credentials. */
|
45
|
+
static VALUE grpc_rb_cServerCredentials = Qnil;
|
46
|
+
|
43
47
|
/* grpc_rb_server_credentials wraps a grpc_server_credentials. It provides a
|
44
48
|
peer ruby object, 'mark' to minimize copying when a server credential is
|
45
49
|
created from ruby. */
|
@@ -82,6 +86,14 @@ static void grpc_rb_server_credentials_mark(void *p) {
|
|
82
86
|
}
|
83
87
|
}
|
84
88
|
|
89
|
+
static const rb_data_type_t grpc_rb_server_credentials_data_type = {
|
90
|
+
"grpc_server_credentials",
|
91
|
+
{grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
|
92
|
+
GRPC_RB_MEMSIZE_UNAVAILABLE},
|
93
|
+
NULL, NULL,
|
94
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
95
|
+
};
|
96
|
+
|
85
97
|
/* Allocates ServerCredential instances.
|
86
98
|
|
87
99
|
Provides safe initial defaults for the instance fields. */
|
@@ -89,8 +101,8 @@ static VALUE grpc_rb_server_credentials_alloc(VALUE cls) {
|
|
89
101
|
grpc_rb_server_credentials *wrapper = ALLOC(grpc_rb_server_credentials);
|
90
102
|
wrapper->wrapped = NULL;
|
91
103
|
wrapper->mark = Qnil;
|
92
|
-
return
|
93
|
-
|
104
|
+
return TypedData_Wrap_Struct(cls, &grpc_rb_server_credentials_data_type,
|
105
|
+
wrapper);
|
94
106
|
}
|
95
107
|
|
96
108
|
/* Clones ServerCredentials instances.
|
@@ -109,11 +121,13 @@ static VALUE grpc_rb_server_credentials_init_copy(VALUE copy, VALUE orig) {
|
|
109
121
|
if (TYPE(orig) != T_DATA ||
|
110
122
|
RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_server_credentials_free) {
|
111
123
|
rb_raise(rb_eTypeError, "not a %s",
|
112
|
-
rb_obj_classname(
|
124
|
+
rb_obj_classname(grpc_rb_cServerCredentials));
|
113
125
|
}
|
114
126
|
|
115
|
-
|
116
|
-
|
127
|
+
TypedData_Get_Struct(orig, grpc_rb_server_credentials,
|
128
|
+
&grpc_rb_server_credentials_data_type, orig_ch);
|
129
|
+
TypedData_Get_Struct(copy, grpc_rb_server_credentials,
|
130
|
+
&grpc_rb_server_credentials_data_type, copy_ch);
|
117
131
|
|
118
132
|
/* use ruby's MEMCPY to make a byte-for-byte copy of the server_credentials
|
119
133
|
wrapper object. */
|
@@ -149,7 +163,8 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
|
|
149
163
|
grpc_rb_server_credentials *wrapper = NULL;
|
150
164
|
grpc_server_credentials *creds = NULL;
|
151
165
|
grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
|
152
|
-
|
166
|
+
TypedData_Get_Struct(self, grpc_rb_server_credentials,
|
167
|
+
&grpc_rb_server_credentials_data_type, wrapper);
|
153
168
|
if (pem_cert_chain == Qnil) {
|
154
169
|
rb_raise(rb_eRuntimeError,
|
155
170
|
"could not create a server credential: nil pem_cert_chain");
|
@@ -180,21 +195,18 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
|
|
180
195
|
return self;
|
181
196
|
}
|
182
197
|
|
183
|
-
/* rb_cServerCredentials is the ruby class that proxies
|
184
|
-
grpc_server_credentials. */
|
185
|
-
VALUE rb_cServerCredentials = Qnil;
|
186
|
-
|
187
198
|
void Init_grpc_server_credentials() {
|
188
|
-
|
189
|
-
rb_define_class_under(
|
199
|
+
grpc_rb_cServerCredentials =
|
200
|
+
rb_define_class_under(grpc_rb_mGrpcCore, "ServerCredentials", rb_cObject);
|
190
201
|
|
191
202
|
/* Allocates an object managed by the ruby runtime */
|
192
|
-
rb_define_alloc_func(
|
203
|
+
rb_define_alloc_func(grpc_rb_cServerCredentials,
|
204
|
+
grpc_rb_server_credentials_alloc);
|
193
205
|
|
194
206
|
/* Provides a ruby constructor and support for dup/clone. */
|
195
|
-
rb_define_method(
|
207
|
+
rb_define_method(grpc_rb_cServerCredentials, "initialize",
|
196
208
|
grpc_rb_server_credentials_init, 3);
|
197
|
-
rb_define_method(
|
209
|
+
rb_define_method(grpc_rb_cServerCredentials, "initialize_copy",
|
198
210
|
grpc_rb_server_credentials_init_copy, 1);
|
199
211
|
|
200
212
|
id_pem_cert_chain = rb_intern("__pem_cert_chain");
|
@@ -205,6 +217,7 @@ void Init_grpc_server_credentials() {
|
|
205
217
|
/* Gets the wrapped grpc_server_credentials from the ruby wrapper */
|
206
218
|
grpc_server_credentials *grpc_rb_get_wrapped_server_credentials(VALUE v) {
|
207
219
|
grpc_rb_server_credentials *wrapper = NULL;
|
208
|
-
|
220
|
+
TypedData_Get_Struct(v, grpc_rb_server_credentials,
|
221
|
+
&grpc_rb_server_credentials_data_type, wrapper);
|
209
222
|
return wrapper->wrapped;
|
210
223
|
}
|
@@ -37,10 +37,6 @@
|
|
37
37
|
#include <ruby.h>
|
38
38
|
#include <grpc/grpc_security.h>
|
39
39
|
|
40
|
-
/* rb_cServerCredentials is the ruby class whose instances proxy
|
41
|
-
grpc_server_credentials. */
|
42
|
-
extern VALUE rb_cServerCredentials;
|
43
|
-
|
44
40
|
/* Initializes the ruby ServerCredentials class. */
|
45
41
|
void Init_grpc_server_credentials();
|
46
42
|
|
data/grpc.gemspec
CHANGED
@@ -13,6 +13,9 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.description = 'Send RPCs from Ruby using GRPC'
|
14
14
|
s.license = 'BSD-3-Clause'
|
15
15
|
|
16
|
+
s.required_ruby_version = '>= 2.0.0'
|
17
|
+
s.requirements << 'libgrpc ~> 0.6.0 needs to be installed'
|
18
|
+
|
16
19
|
s.files = `git ls-files`.split("\n")
|
17
20
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
21
|
s.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
|
@@ -22,16 +25,16 @@ Gem::Specification.new do |s|
|
|
22
25
|
s.platform = Gem::Platform::RUBY
|
23
26
|
|
24
27
|
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
|
25
|
-
s.add_dependency 'googleauth', '~> 0.
|
26
|
-
s.add_dependency 'logging', '~>
|
28
|
+
s.add_dependency 'googleauth', '~> 0.4' # reqd for interop tests
|
29
|
+
s.add_dependency 'logging', '~> 2.0'
|
27
30
|
s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests
|
28
|
-
s.add_dependency 'xray', '~> 1.1'
|
29
31
|
|
30
|
-
s.add_development_dependency '
|
31
|
-
s.add_development_dependency '
|
32
|
-
s.add_development_dependency 'rake
|
33
|
-
s.add_development_dependency '
|
34
|
-
s.add_development_dependency 'rspec', '~> 3.
|
32
|
+
s.add_development_dependency 'simplecov', '~> 0.9'
|
33
|
+
s.add_development_dependency 'bundler', '~> 1.9'
|
34
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
35
|
+
s.add_development_dependency 'rake-compiler', '~> 0.9'
|
36
|
+
s.add_development_dependency 'rspec', '~> 3.2'
|
37
|
+
s.add_development_dependency 'rubocop', '~> 0.30'
|
35
38
|
|
36
39
|
s.extensions = %w(ext/grpc/extconf.rb)
|
37
40
|
end
|
data/lib/grpc.rb
CHANGED
@@ -30,8 +30,8 @@
|
|
30
30
|
require 'grpc/errors'
|
31
31
|
require 'grpc/grpc'
|
32
32
|
require 'grpc/logconfig'
|
33
|
+
require 'grpc/notifier'
|
33
34
|
require 'grpc/version'
|
34
|
-
require 'grpc/core/event'
|
35
35
|
require 'grpc/core/time_consts'
|
36
36
|
require 'grpc/generic/active_call'
|
37
37
|
require 'grpc/generic/client_stub'
|
data/lib/grpc/errors.rb
CHANGED
@@ -31,23 +31,20 @@ require 'grpc'
|
|
31
31
|
|
32
32
|
# GRPC contains the General RPC module.
|
33
33
|
module GRPC
|
34
|
-
# OutOfTime is an exception class that indicates that an RPC exceeded its
|
35
|
-
# deadline.
|
36
|
-
OutOfTime = Class.new(StandardError)
|
37
|
-
|
38
34
|
# BadStatus is an exception class that indicates that an error occurred at
|
39
35
|
# either end of a GRPC connection. When raised, it indicates that a status
|
40
36
|
# error should be returned to the other end of a GRPC connection; when
|
41
37
|
# caught it means that this end received a status error.
|
42
38
|
class BadStatus < StandardError
|
43
|
-
attr_reader :code, :details
|
39
|
+
attr_reader :code, :details, :metadata
|
44
40
|
|
45
41
|
# @param code [Numeric] the status code
|
46
42
|
# @param details [String] the details of the exception
|
47
|
-
def initialize(code, details = 'unknown cause')
|
43
|
+
def initialize(code, details = 'unknown cause', **kw)
|
48
44
|
super("#{code}:#{details}")
|
49
45
|
@code = code
|
50
46
|
@details = details
|
47
|
+
@metadata = kw
|
51
48
|
end
|
52
49
|
|
53
50
|
# Converts the exception to a GRPC::Status for use in the networking
|
@@ -55,7 +52,11 @@ module GRPC
|
|
55
52
|
#
|
56
53
|
# @return [Status] with the same code and details
|
57
54
|
def to_status
|
58
|
-
Status.new(code, details)
|
55
|
+
Struct::Status.new(code, details, @metadata)
|
59
56
|
end
|
60
57
|
end
|
58
|
+
|
59
|
+
# Cancelled is an exception class that indicates that an rpc was cancelled.
|
60
|
+
class Cancelled < StandardError
|
61
|
+
end
|
61
62
|
end
|
@@ -30,10 +30,23 @@
|
|
30
30
|
require 'forwardable'
|
31
31
|
require 'grpc/generic/bidi_call'
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
class Struct
|
34
|
+
# BatchResult is the struct returned by calls to call#start_batch.
|
35
|
+
class BatchResult
|
36
|
+
# check_status returns the status, raising an error if the status
|
37
|
+
# is non-nil and not OK.
|
38
|
+
def check_status
|
39
|
+
return nil if status.nil?
|
40
|
+
fail GRPC::Cancelled if status.code == GRPC::Core::StatusCodes::CANCELLED
|
41
|
+
if status.code != GRPC::Core::StatusCodes::OK
|
42
|
+
# raise BadStatus, propagating the metadata if present.
|
43
|
+
md = status.metadata
|
44
|
+
with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }]
|
45
|
+
fail GRPC::BadStatus.new(status.code, status.details, **with_sym_keys)
|
46
|
+
end
|
47
|
+
status
|
48
|
+
end
|
49
|
+
end
|
37
50
|
end
|
38
51
|
|
39
52
|
# GRPC contains the General RPC module.
|
@@ -41,10 +54,12 @@ module GRPC
|
|
41
54
|
# The ActiveCall class provides simple methods for sending marshallable
|
42
55
|
# data to a call
|
43
56
|
class ActiveCall
|
44
|
-
include Core::CompletionType
|
45
57
|
include Core::StatusCodes
|
46
58
|
include Core::TimeConsts
|
59
|
+
include Core::CallOps
|
60
|
+
extend Forwardable
|
47
61
|
attr_reader(:deadline)
|
62
|
+
def_delegators :@call, :cancel, :metadata
|
48
63
|
|
49
64
|
# client_invoke begins a client invocation.
|
50
65
|
#
|
@@ -61,15 +76,14 @@ module GRPC
|
|
61
76
|
# @param q [CompletionQueue] the completion queue
|
62
77
|
# @param deadline [Fixnum,TimeSpec] the deadline
|
63
78
|
def self.client_invoke(call, q, _deadline, **kw)
|
64
|
-
fail(
|
79
|
+
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call
|
65
80
|
unless q.is_a? Core::CompletionQueue
|
66
|
-
fail(
|
81
|
+
fail(TypeError, '!Core::CompletionQueue')
|
67
82
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
[finished_tag, client_metadata_read]
|
83
|
+
metadata_tag = Object.new
|
84
|
+
call.run_batch(q, metadata_tag, INFINITE_FUTURE,
|
85
|
+
SEND_INITIAL_METADATA => kw)
|
86
|
+
metadata_tag
|
73
87
|
end
|
74
88
|
|
75
89
|
# Creates an ActiveCall.
|
@@ -91,69 +105,27 @@ module GRPC
|
|
91
105
|
# @param marshal [Function] f(obj)->string that marshal requests
|
92
106
|
# @param unmarshal [Function] f(string)->obj that unmarshals responses
|
93
107
|
# @param deadline [Fixnum] the deadline for the call to complete
|
94
|
-
# @param
|
95
|
-
# if the call has begun
|
96
|
-
# @param read_metadata_tag [Object] the object used as the call's finish
|
97
|
-
# tag, if the call has begun
|
108
|
+
# @param metadata_tag [Object] the object use obtain metadata for clients
|
98
109
|
# @param started [true|false] indicates if the call has begun
|
99
|
-
def initialize(call, q, marshal, unmarshal, deadline,
|
100
|
-
|
101
|
-
fail(
|
110
|
+
def initialize(call, q, marshal, unmarshal, deadline, started: true,
|
111
|
+
metadata_tag: nil)
|
112
|
+
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call
|
102
113
|
unless q.is_a? Core::CompletionQueue
|
103
|
-
fail(
|
114
|
+
fail(TypeError, '!Core::CompletionQueue')
|
104
115
|
end
|
105
116
|
@call = call
|
106
117
|
@cq = q
|
107
118
|
@deadline = deadline
|
108
|
-
@finished_tag = finished_tag
|
109
|
-
@read_metadata_tag = read_metadata_tag
|
110
119
|
@marshal = marshal
|
111
120
|
@started = started
|
112
121
|
@unmarshal = unmarshal
|
122
|
+
@metadata_tag = metadata_tag
|
113
123
|
end
|
114
124
|
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
def status
|
120
|
-
@call.status
|
121
|
-
end
|
122
|
-
|
123
|
-
# Obtains the metadata of the call.
|
124
|
-
#
|
125
|
-
# At the start of the call this will be nil. During the call this gets
|
126
|
-
# some values as soon as the other end of the connection acknowledges the
|
127
|
-
# request.
|
128
|
-
#
|
129
|
-
# @return this calls's metadata
|
130
|
-
def metadata
|
131
|
-
@call.metadata
|
132
|
-
end
|
133
|
-
|
134
|
-
# Cancels the call.
|
135
|
-
#
|
136
|
-
# Cancels the call. The call does not return any result, but once this it
|
137
|
-
# has been called, the call should eventually terminate. Due to potential
|
138
|
-
# races between the execution of the cancel and the in-flight request, the
|
139
|
-
# result of the call after calling #cancel is indeterminate:
|
140
|
-
#
|
141
|
-
# - the call may terminate with a BadStatus exception, with code=CANCELLED
|
142
|
-
# - the call may terminate with OK Status, and return a response
|
143
|
-
# - the call may terminate with a different BadStatus exception if that
|
144
|
-
# was happening
|
145
|
-
def cancel
|
146
|
-
@call.cancel
|
147
|
-
end
|
148
|
-
|
149
|
-
# indicates if the call is shutdown
|
150
|
-
def shutdown
|
151
|
-
@shutdown ||= false
|
152
|
-
end
|
153
|
-
|
154
|
-
# indicates if the call is cancelled.
|
155
|
-
def cancelled
|
156
|
-
@cancelled ||= false
|
125
|
+
# output_metadata are provides access to hash that can be used to
|
126
|
+
# save metadata to be sent as trailer
|
127
|
+
def output_metadata
|
128
|
+
@output_metadata ||= {}
|
157
129
|
end
|
158
130
|
|
159
131
|
# multi_req_view provides a restricted view of this ActiveCall for use
|
@@ -176,128 +148,94 @@ module GRPC
|
|
176
148
|
|
177
149
|
# writes_done indicates that all writes are completed.
|
178
150
|
#
|
179
|
-
# It blocks until the remote endpoint acknowledges
|
180
|
-
#
|
181
|
-
#
|
151
|
+
# It blocks until the remote endpoint acknowledges with at status unless
|
152
|
+
# assert_finished is set to false. Any calls to #remote_send after this
|
153
|
+
# call will fail.
|
182
154
|
#
|
183
155
|
# @param assert_finished [true, false] when true(default), waits for
|
184
156
|
# FINISHED.
|
185
157
|
def writes_done(assert_finished = true)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
ensure
|
192
|
-
ev.close
|
193
|
-
end
|
194
|
-
|
158
|
+
ops = {
|
159
|
+
SEND_CLOSE_FROM_CLIENT => nil
|
160
|
+
}
|
161
|
+
ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished
|
162
|
+
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
|
195
163
|
return unless assert_finished
|
196
|
-
|
197
|
-
fail 'unexpected nil event' if ev.nil?
|
198
|
-
ev.close
|
199
|
-
@call.status
|
164
|
+
batch_result.check_status
|
200
165
|
end
|
201
166
|
|
202
|
-
# finished waits until
|
167
|
+
# finished waits until a client call is completed.
|
203
168
|
#
|
204
|
-
# It blocks until the remote endpoint acknowledges by sending a
|
205
|
-
# event.
|
169
|
+
# It blocks until the remote endpoint acknowledges by sending a status.
|
206
170
|
def finished
|
207
|
-
|
208
|
-
|
209
|
-
|
171
|
+
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE,
|
172
|
+
RECV_STATUS_ON_CLIENT => nil)
|
173
|
+
unless batch_result.status.nil?
|
210
174
|
if @call.metadata.nil?
|
211
|
-
@call.metadata =
|
175
|
+
@call.metadata = batch_result.status.metadata
|
212
176
|
else
|
213
|
-
@call.metadata.merge!(
|
177
|
+
@call.metadata.merge!(batch_result.status.metadata)
|
214
178
|
end
|
215
|
-
|
216
|
-
if ev.result.code != Core::StatusCodes::OK
|
217
|
-
fail BadStatus.new(ev.result.code, ev.result.details)
|
218
|
-
end
|
219
|
-
res = ev.result
|
220
|
-
ensure
|
221
|
-
ev.close
|
222
179
|
end
|
223
|
-
|
180
|
+
batch_result.check_status
|
224
181
|
end
|
225
182
|
|
226
183
|
# remote_send sends a request to the remote endpoint.
|
227
184
|
#
|
228
|
-
# It blocks until the remote endpoint
|
229
|
-
# WRITE_ACCEPTED. req can be marshalled already.
|
185
|
+
# It blocks until the remote endpoint accepts the message.
|
230
186
|
#
|
231
187
|
# @param req [Object, String] the object to send or it's marshal form.
|
232
188
|
# @param marshalled [false, true] indicates if the object is already
|
233
189
|
# marshalled.
|
234
190
|
def remote_send(req, marshalled = false)
|
235
|
-
|
236
|
-
logger.debug("sending #{req.inspect}, marshalled? #{marshalled}")
|
191
|
+
logger.debug("sending #{req}, marshalled? #{marshalled}")
|
237
192
|
if marshalled
|
238
193
|
payload = req
|
239
194
|
else
|
240
195
|
payload = @marshal.call(req)
|
241
196
|
end
|
242
|
-
@call.
|
243
|
-
|
244
|
-
# call queue#pluck, and wait for WRITE_ACCEPTED, so as not to return
|
245
|
-
# until the flow control allows another send on this call.
|
246
|
-
ev = @cq.pluck(self, INFINITE_FUTURE)
|
247
|
-
begin
|
248
|
-
assert_event_type(ev, WRITE_ACCEPTED)
|
249
|
-
ensure
|
250
|
-
ev.close
|
251
|
-
end
|
197
|
+
@call.run_batch(@cq, self, INFINITE_FUTURE, SEND_MESSAGE => payload)
|
252
198
|
end
|
253
199
|
|
254
|
-
# send_status sends a status to the remote endpoint
|
200
|
+
# send_status sends a status to the remote endpoint.
|
255
201
|
#
|
256
202
|
# @param code [int] the status code to send
|
257
203
|
# @param details [String] details
|
258
204
|
# @param assert_finished [true, false] when true(default), waits for
|
259
205
|
# FINISHED.
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
return finished if assert_finished
|
206
|
+
#
|
207
|
+
# == Keyword Arguments ==
|
208
|
+
# any keyword arguments are treated as metadata to be sent to the server
|
209
|
+
# if a keyword value is a list, multiple metadata for it's key are sent
|
210
|
+
def send_status(code = OK, details = '', assert_finished = false, **kw)
|
211
|
+
ops = {
|
212
|
+
SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, kw)
|
213
|
+
}
|
214
|
+
ops[RECV_CLOSE_ON_SERVER] = nil if assert_finished
|
215
|
+
@call.run_batch(@cq, self, INFINITE_FUTURE, ops)
|
271
216
|
nil
|
272
217
|
end
|
273
218
|
|
274
219
|
# remote_read reads a response from the remote endpoint.
|
275
220
|
#
|
276
|
-
# It blocks until the remote endpoint
|
277
|
-
# a
|
278
|
-
#
|
279
|
-
# BadStatus
|
221
|
+
# It blocks until the remote endpoint replies with a message or status.
|
222
|
+
# On receiving a message, it returns the response after unmarshalling it.
|
223
|
+
# On receiving a status, it returns nil if the status is OK, otherwise
|
224
|
+
# raising BadStatus
|
280
225
|
def remote_read
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
@
|
226
|
+
ops = { RECV_MESSAGE => nil }
|
227
|
+
ops[RECV_INITIAL_METADATA] = nil unless @metadata_tag.nil?
|
228
|
+
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
|
229
|
+
unless @metadata_tag.nil?
|
230
|
+
@call.metadata = batch_result.metadata
|
231
|
+
@metadata_tag = nil
|
286
232
|
end
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
unless ev.result.nil?
|
294
|
-
logger.debug("received req.to_s: #{ev.result}")
|
295
|
-
res = @unmarshal.call(ev.result.to_s)
|
296
|
-
logger.debug("received_req (unmarshalled): #{res.inspect}")
|
297
|
-
return res
|
298
|
-
end
|
299
|
-
ensure
|
300
|
-
ev.close
|
233
|
+
logger.debug("received req: #{batch_result}")
|
234
|
+
unless batch_result.nil? || batch_result.message.nil?
|
235
|
+
logger.debug("received req.to_s: #{batch_result.message}")
|
236
|
+
res = @unmarshal.call(batch_result.message)
|
237
|
+
logger.debug("received_req (unmarshalled): #{res.inspect}")
|
238
|
+
return res
|
301
239
|
end
|
302
240
|
logger.debug('found nil; the final response has been sent')
|
303
241
|
nil
|
@@ -324,7 +262,6 @@ module GRPC
|
|
324
262
|
return enum_for(:each_remote_read) unless block_given?
|
325
263
|
loop do
|
326
264
|
resp = remote_read
|
327
|
-
break if resp.is_a? Struct::Status # is an OK status
|
328
265
|
break if resp.nil? # the last response was received
|
329
266
|
yield resp
|
330
267
|
end
|
@@ -379,6 +316,9 @@ module GRPC
|
|
379
316
|
response = remote_read
|
380
317
|
finished unless response.is_a? Struct::Status
|
381
318
|
response
|
319
|
+
rescue GRPC::Core::CallError => e
|
320
|
+
finished # checks for Cancelled
|
321
|
+
raise e
|
382
322
|
end
|
383
323
|
|
384
324
|
# client_streamer sends a stream of requests to a GRPC server, and
|
@@ -402,6 +342,9 @@ module GRPC
|
|
402
342
|
response = remote_read
|
403
343
|
finished unless response.is_a? Struct::Status
|
404
344
|
response
|
345
|
+
rescue GRPC::Core::CallError => e
|
346
|
+
finished # checks for Cancelled
|
347
|
+
raise e
|
405
348
|
end
|
406
349
|
|
407
350
|
# server_streamer sends one request to the GRPC server, which yields a
|
@@ -428,6 +371,9 @@ module GRPC
|
|
428
371
|
replies = enum_for(:each_remote_read_then_finish)
|
429
372
|
return replies unless block_given?
|
430
373
|
replies.each { |r| yield r }
|
374
|
+
rescue GRPC::Core::CallError => e
|
375
|
+
finished # checks for Cancelled
|
376
|
+
raise e
|
431
377
|
end
|
432
378
|
|
433
379
|
# bidi_streamer sends a stream of requests to the GRPC server, and yields
|
@@ -461,9 +407,11 @@ module GRPC
|
|
461
407
|
# @return [Enumerator, nil] a response Enumerator
|
462
408
|
def bidi_streamer(requests, **kw, &blk)
|
463
409
|
start_call(**kw) unless @started
|
464
|
-
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline
|
465
|
-
@finished_tag)
|
410
|
+
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline)
|
466
411
|
bd.run_on_client(requests, &blk)
|
412
|
+
rescue GRPC::Core::CallError => e
|
413
|
+
finished # checks for Cancelled
|
414
|
+
raise e
|
467
415
|
end
|
468
416
|
|
469
417
|
# run_server_bidi orchestrates a BiDi stream processing on a server.
|
@@ -478,16 +426,16 @@ module GRPC
|
|
478
426
|
#
|
479
427
|
# @param gen_each_reply [Proc] generates the BiDi stream replies
|
480
428
|
def run_server_bidi(gen_each_reply)
|
481
|
-
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline
|
482
|
-
@finished_tag)
|
429
|
+
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline)
|
483
430
|
bd.run_on_server(gen_each_reply)
|
484
431
|
end
|
485
432
|
|
486
433
|
private
|
487
434
|
|
435
|
+
# Starts the call if not already started
|
488
436
|
def start_call(**kw)
|
489
|
-
|
490
|
-
@
|
437
|
+
return if @started
|
438
|
+
@metadata_tag = ActiveCall.client_invoke(@call, @cq, @deadline, **kw)
|
491
439
|
@started = true
|
492
440
|
end
|
493
441
|
|
@@ -505,32 +453,17 @@ module GRPC
|
|
505
453
|
|
506
454
|
# SingleReqView limits access to an ActiveCall's methods for use in server
|
507
455
|
# handlers that receive just one request.
|
508
|
-
SingleReqView = view_class(:cancelled, :deadline, :metadata
|
456
|
+
SingleReqView = view_class(:cancelled, :deadline, :metadata,
|
457
|
+
:output_metadata)
|
509
458
|
|
510
459
|
# MultiReqView limits access to an ActiveCall's methods for use in
|
511
460
|
# server client_streamer handlers.
|
512
461
|
MultiReqView = view_class(:cancelled, :deadline, :each_queued_msg,
|
513
|
-
:each_remote_read, :metadata)
|
462
|
+
:each_remote_read, :metadata, :output_metadata)
|
514
463
|
|
515
464
|
# Operation limits access to an ActiveCall's methods for use as
|
516
465
|
# a Operation on the client.
|
517
466
|
Operation = view_class(:cancel, :cancelled, :deadline, :execute,
|
518
|
-
:metadata, :status)
|
519
|
-
|
520
|
-
# confirms that no events are enqueued, and that the queue is not
|
521
|
-
# shutdown.
|
522
|
-
def assert_queue_is_ready
|
523
|
-
ev = nil
|
524
|
-
begin
|
525
|
-
ev = @cq.pluck(self, ZERO)
|
526
|
-
fail "unexpected event #{ev.inspect}" unless ev.nil?
|
527
|
-
rescue OutOfTime
|
528
|
-
logging.debug('timed out waiting for next event')
|
529
|
-
# expected, nothing should be on the queue and the deadline was ZERO,
|
530
|
-
# except things using another tag
|
531
|
-
ensure
|
532
|
-
ev.close unless ev.nil?
|
533
|
-
end
|
534
|
-
end
|
467
|
+
:metadata, :status, :start_call)
|
535
468
|
end
|
536
469
|
end
|