grpc 1.0.1-universal-darwin → 1.1.2-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.
- checksums.yaml +4 -4
- data/etc/roots.pem +39 -111
- data/src/ruby/ext/grpc/extconf.rb +0 -1
- data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -7
- data/src/ruby/ext/grpc/rb_call.c +15 -5
- data/src/ruby/ext/grpc/rb_channel.c +1 -1
- data/src/ruby/ext/grpc/rb_compression_options.c +466 -0
- data/src/ruby/ext/grpc/rb_compression_options.h +44 -0
- data/src/ruby/ext/grpc/rb_grpc.c +3 -1
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +198 -190
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +306 -294
- data/src/ruby/ext/grpc/rb_server.c +18 -12
- data/src/ruby/lib/grpc/2.0/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.1/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.2/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.3/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.4/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/errors.rb +154 -2
- data/src/ruby/lib/grpc/generic/active_call.rb +144 -63
- data/src/ruby/lib/grpc/generic/bidi_call.rb +18 -2
- data/src/ruby/lib/grpc/generic/client_stub.rb +7 -5
- data/src/ruby/lib/grpc/generic/rpc_desc.rb +39 -13
- data/src/ruby/lib/grpc/generic/rpc_server.rb +51 -24
- data/src/ruby/lib/grpc/generic/service.rb +3 -2
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/grpc/health/checker.rb +3 -1
- data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +7 -0
- data/src/ruby/pb/test/client.rb +307 -7
- data/src/ruby/pb/test/server.rb +26 -1
- data/src/ruby/spec/compression_options_spec.rb +164 -0
- data/src/ruby/spec/error_sanity_spec.rb +64 -0
- data/src/ruby/spec/generic/active_call_spec.rb +290 -12
- data/src/ruby/spec/generic/client_stub_spec.rb +91 -41
- data/src/ruby/spec/generic/rpc_desc_spec.rb +36 -16
- data/src/ruby/spec/generic/rpc_server_pool_spec.rb +22 -28
- data/src/ruby/spec/generic/rpc_server_spec.rb +6 -6
- data/src/ruby/spec/pb/health/checker_spec.rb +27 -19
- data/src/ruby/spec/spec_helper.rb +2 -0
- metadata +18 -8
@@ -37,6 +37,7 @@
|
|
37
37
|
#include "rb_server.h"
|
38
38
|
|
39
39
|
#include <grpc/grpc.h>
|
40
|
+
#include <grpc/support/atm.h>
|
40
41
|
#include <grpc/grpc_security.h>
|
41
42
|
#include <grpc/support/log.h>
|
42
43
|
#include "rb_call.h"
|
@@ -59,22 +60,26 @@ typedef struct grpc_rb_server {
|
|
59
60
|
/* The actual server */
|
60
61
|
grpc_server *wrapped;
|
61
62
|
grpc_completion_queue *queue;
|
63
|
+
gpr_atm shutdown_started;
|
62
64
|
} grpc_rb_server;
|
63
65
|
|
64
66
|
static void destroy_server(grpc_rb_server *server, gpr_timespec deadline) {
|
65
67
|
grpc_event ev;
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
// This can be started by app or implicitly by GC. Avoid a race between these.
|
69
|
+
if (gpr_atm_full_fetch_add(&server->shutdown_started, (gpr_atm)1) == 0) {
|
70
|
+
if (server->wrapped != NULL) {
|
71
|
+
grpc_server_shutdown_and_notify(server->wrapped, server->queue, NULL);
|
72
|
+
ev = rb_completion_queue_pluck(server->queue, NULL, deadline, NULL);
|
73
|
+
if (ev.type == GRPC_QUEUE_TIMEOUT) {
|
74
|
+
grpc_server_cancel_all_calls(server->wrapped);
|
75
|
+
rb_completion_queue_pluck(server->queue, NULL,
|
76
|
+
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
77
|
+
}
|
78
|
+
grpc_server_destroy(server->wrapped);
|
79
|
+
grpc_rb_completion_queue_destroy(server->queue);
|
80
|
+
server->wrapped = NULL;
|
81
|
+
server->queue = NULL;
|
73
82
|
}
|
74
|
-
grpc_server_destroy(server->wrapped);
|
75
|
-
grpc_rb_completion_queue_destroy(server->queue);
|
76
|
-
server->wrapped = NULL;
|
77
|
-
server->queue = NULL;
|
78
83
|
}
|
79
84
|
}
|
80
85
|
|
@@ -115,6 +120,7 @@ static const rb_data_type_t grpc_rb_server_data_type = {
|
|
115
120
|
static VALUE grpc_rb_server_alloc(VALUE cls) {
|
116
121
|
grpc_rb_server *wrapper = ALLOC(grpc_rb_server);
|
117
122
|
wrapper->wrapped = NULL;
|
123
|
+
wrapper->shutdown_started = (gpr_atm)0;
|
118
124
|
return TypedData_Wrap_Struct(cls, &grpc_rb_server_data_type, wrapper);
|
119
125
|
}
|
120
126
|
|
@@ -218,7 +224,7 @@ static VALUE grpc_rb_server_request_call(VALUE self) {
|
|
218
224
|
grpc_rb_sNewServerRpc, rb_str_new2(st.details.method),
|
219
225
|
rb_str_new2(st.details.host),
|
220
226
|
rb_funcall(rb_cTime, id_at, 2, INT2NUM(deadline.tv_sec),
|
221
|
-
INT2NUM(deadline.tv_nsec)),
|
227
|
+
INT2NUM(deadline.tv_nsec / 1000)),
|
222
228
|
grpc_rb_md_ary_to_h(&st.md_ary), grpc_rb_wrap_call(call, call_queue),
|
223
229
|
NULL);
|
224
230
|
grpc_request_call_stack_cleanup(&st);
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/src/ruby/lib/grpc/errors.rb
CHANGED
@@ -35,9 +35,18 @@ module GRPC
|
|
35
35
|
# either end of a GRPC connection. When raised, it indicates that a status
|
36
36
|
# error should be returned to the other end of a GRPC connection; when
|
37
37
|
# caught it means that this end received a status error.
|
38
|
+
#
|
39
|
+
# There is also subclass of BadStatus in this module for each GRPC status.
|
40
|
+
# E.g., the GRPC::Cancelled class corresponds to status CANCELLED.
|
41
|
+
#
|
42
|
+
# See
|
43
|
+
# https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/status.h
|
44
|
+
# for detailed descriptions of each status code.
|
38
45
|
class BadStatus < StandardError
|
39
46
|
attr_reader :code, :details, :metadata
|
40
47
|
|
48
|
+
include GRPC::Core::StatusCodes
|
49
|
+
|
41
50
|
# @param code [Numeric] the status code
|
42
51
|
# @param details [String] the details of the exception
|
43
52
|
# @param metadata [Hash] the error's metadata
|
@@ -55,9 +64,152 @@ module GRPC
|
|
55
64
|
def to_status
|
56
65
|
Struct::Status.new(code, details, @metadata)
|
57
66
|
end
|
67
|
+
|
68
|
+
def self.new_status_exception(code, details = 'unkown cause', metadata = {})
|
69
|
+
codes = {}
|
70
|
+
codes[OK] = Ok
|
71
|
+
codes[CANCELLED] = Cancelled
|
72
|
+
codes[UNKNOWN] = Unknown
|
73
|
+
codes[INVALID_ARGUMENT] = InvalidArgument
|
74
|
+
codes[DEADLINE_EXCEEDED] = DeadlineExceeded
|
75
|
+
codes[NOT_FOUND] = NotFound
|
76
|
+
codes[ALREADY_EXISTS] = AlreadyExists
|
77
|
+
codes[PERMISSION_DENIED] = PermissionDenied
|
78
|
+
codes[UNAUTHENTICATED] = Unauthenticated
|
79
|
+
codes[RESOURCE_EXHAUSTED] = ResourceExhausted
|
80
|
+
codes[FAILED_PRECONDITION] = FailedPrecondition
|
81
|
+
codes[ABORTED] = Aborted
|
82
|
+
codes[OUT_OF_RANGE] = OutOfRange
|
83
|
+
codes[UNIMPLEMENTED] = Unimplemented
|
84
|
+
codes[INTERNAL] = Internal
|
85
|
+
codes[UNIMPLEMENTED] = Unimplemented
|
86
|
+
codes[UNAVAILABLE] = Unavailable
|
87
|
+
codes[DATA_LOSS] = DataLoss
|
88
|
+
|
89
|
+
if codes[code].nil?
|
90
|
+
BadStatus.new(code, details, metadata)
|
91
|
+
else
|
92
|
+
codes[code].new(details, metadata)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# GRPC status code corresponding to status OK
|
98
|
+
class Ok < BadStatus
|
99
|
+
def initialize(details = 'unknown cause', metadata = {})
|
100
|
+
super(Core::StatusCodes::OK, details, metadata)
|
101
|
+
end
|
58
102
|
end
|
59
103
|
|
60
|
-
#
|
61
|
-
class Cancelled <
|
104
|
+
# GRPC status code corresponding to status CANCELLED
|
105
|
+
class Cancelled < BadStatus
|
106
|
+
def initialize(details = 'unknown cause', metadata = {})
|
107
|
+
super(Core::StatusCodes::CANCELLED, details, metadata)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# GRPC status code corresponding to status UNKNOWN
|
112
|
+
class Unknown < BadStatus
|
113
|
+
def initialize(details = 'unknown cause', metadata = {})
|
114
|
+
super(Core::StatusCodes::UNKNOWN, details, metadata)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# GRPC status code corresponding to status INVALID_ARGUMENT
|
119
|
+
class InvalidArgument < BadStatus
|
120
|
+
def initialize(details = 'unknown cause', metadata = {})
|
121
|
+
super(Core::StatusCodes::INVALID_ARGUMENT, details, metadata)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# GRPC status code corresponding to status DEADLINE_EXCEEDED
|
126
|
+
class DeadlineExceeded < BadStatus
|
127
|
+
def initialize(details = 'unknown cause', metadata = {})
|
128
|
+
super(Core::StatusCodes::DEADLINE_EXCEEDED, details, metadata)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# GRPC status code corresponding to status NOT_FOUND
|
133
|
+
class NotFound < BadStatus
|
134
|
+
def initialize(details = 'unknown cause', metadata = {})
|
135
|
+
super(Core::StatusCodes::NOT_FOUND, details, metadata)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# GRPC status code corresponding to status ALREADY_EXISTS
|
140
|
+
class AlreadyExists < BadStatus
|
141
|
+
def initialize(details = 'unknown cause', metadata = {})
|
142
|
+
super(Core::StatusCodes::ALREADY_EXISTS, details, metadata)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# GRPC status code corresponding to status PERMISSION_DENIED
|
147
|
+
class PermissionDenied < BadStatus
|
148
|
+
def initialize(details = 'unknown cause', metadata = {})
|
149
|
+
super(Core::StatusCodes::PERMISSION_DENIED, details, metadata)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# GRPC status code corresponding to status UNAUTHENTICATED
|
154
|
+
class Unauthenticated < BadStatus
|
155
|
+
def initialize(details = 'unknown cause', metadata = {})
|
156
|
+
super(Core::StatusCodes::UNAUTHENTICATED, details, metadata)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# GRPC status code corresponding to status RESOURCE_EXHAUSTED
|
161
|
+
class ResourceExhausted < BadStatus
|
162
|
+
def initialize(details = 'unknown cause', metadata = {})
|
163
|
+
super(Core::StatusCodes::RESOURCE_EXHAUSTED, details, metadata)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# GRPC status code corresponding to status FAILED_PRECONDITION
|
168
|
+
class FailedPrecondition < BadStatus
|
169
|
+
def initialize(details = 'unknown cause', metadata = {})
|
170
|
+
super(Core::StatusCodes::FAILED_PRECONDITION, details, metadata)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# GRPC status code corresponding to status ABORTED
|
175
|
+
class Aborted < BadStatus
|
176
|
+
def initialize(details = 'unknown cause', metadata = {})
|
177
|
+
super(Core::StatusCodes::ABORTED, details, metadata)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# GRPC status code corresponding to status OUT_OF_RANGE
|
182
|
+
class OutOfRange < BadStatus
|
183
|
+
def initialize(details = 'unknown cause', metadata = {})
|
184
|
+
super(Core::StatusCodes::OUT_OF_RANGE, details, metadata)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# GRPC status code corresponding to status UNIMPLEMENTED
|
189
|
+
class Unimplemented < BadStatus
|
190
|
+
def initialize(details = 'unknown cause', metadata = {})
|
191
|
+
super(Core::StatusCodes::UNIMPLEMENTED, details, metadata)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# GRPC status code corresponding to status INTERNAL
|
196
|
+
class Internal < BadStatus
|
197
|
+
def initialize(details = 'unknown cause', metadata = {})
|
198
|
+
super(Core::StatusCodes::INTERNAL, details, metadata)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# GRPC status code corresponding to status UNAVAILABLE
|
203
|
+
class Unavailable < BadStatus
|
204
|
+
def initialize(details = 'unknown cause', metadata = {})
|
205
|
+
super(Core::StatusCodes::UNAVAILABLE, details, metadata)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# GRPC status code corresponding to status DATA_LOSS
|
210
|
+
class DataLoss < BadStatus
|
211
|
+
def initialize(details = 'unknown cause', metadata = {})
|
212
|
+
super(Core::StatusCodes::DATA_LOSS, details, metadata)
|
213
|
+
end
|
62
214
|
end
|
63
215
|
end
|
@@ -43,7 +43,8 @@ class Struct
|
|
43
43
|
GRPC.logger.debug("Failing with status #{status}")
|
44
44
|
# raise BadStatus, propagating the metadata if present.
|
45
45
|
md = status.metadata
|
46
|
-
fail GRPC::BadStatus.
|
46
|
+
fail GRPC::BadStatus.new_status_exception(
|
47
|
+
status.code, status.details, md)
|
47
48
|
end
|
48
49
|
status
|
49
50
|
end
|
@@ -58,7 +59,7 @@ module GRPC
|
|
58
59
|
include Core::TimeConsts
|
59
60
|
include Core::CallOps
|
60
61
|
extend Forwardable
|
61
|
-
attr_reader
|
62
|
+
attr_reader :deadline, :metadata_sent, :metadata_to_send
|
62
63
|
def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=,
|
63
64
|
:peer, :peer_cert, :trailing_metadata
|
64
65
|
|
@@ -101,7 +102,7 @@ module GRPC
|
|
101
102
|
# @param metadata_received [true|false] indicates if metadata has already
|
102
103
|
# been received. Should always be true for server calls
|
103
104
|
def initialize(call, marshal, unmarshal, deadline, started: true,
|
104
|
-
metadata_received: false)
|
105
|
+
metadata_received: false, metadata_to_send: nil)
|
105
106
|
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call
|
106
107
|
@call = call
|
107
108
|
@deadline = deadline
|
@@ -110,6 +111,20 @@ module GRPC
|
|
110
111
|
@metadata_received = metadata_received
|
111
112
|
@metadata_sent = started
|
112
113
|
@op_notifier = nil
|
114
|
+
|
115
|
+
fail(ArgumentError, 'Already sent md') if started && metadata_to_send
|
116
|
+
@metadata_to_send = metadata_to_send || {} unless started
|
117
|
+
@send_initial_md_mutex = Mutex.new
|
118
|
+
end
|
119
|
+
|
120
|
+
# Sends the initial metadata that has yet to be sent.
|
121
|
+
# Does nothing if metadata has already been sent for this call.
|
122
|
+
def send_initial_metadata
|
123
|
+
@send_initial_md_mutex.synchronize do
|
124
|
+
return if @metadata_sent
|
125
|
+
@metadata_tag = ActiveCall.client_invoke(@call, @metadata_to_send)
|
126
|
+
@metadata_sent = true
|
127
|
+
end
|
113
128
|
end
|
114
129
|
|
115
130
|
# output_metadata are provides access to hash that can be used to
|
@@ -142,41 +157,25 @@ module GRPC
|
|
142
157
|
Operation.new(self)
|
143
158
|
end
|
144
159
|
|
145
|
-
# writes_done indicates that all writes are completed.
|
146
|
-
#
|
147
|
-
# It blocks until the remote endpoint acknowledges with at status unless
|
148
|
-
# assert_finished is set to false. Any calls to #remote_send after this
|
149
|
-
# call will fail.
|
150
|
-
#
|
151
|
-
# @param assert_finished [true, false] when true(default), waits for
|
152
|
-
# FINISHED.
|
153
|
-
def writes_done(assert_finished = true)
|
154
|
-
ops = {
|
155
|
-
SEND_CLOSE_FROM_CLIENT => nil
|
156
|
-
}
|
157
|
-
ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished
|
158
|
-
batch_result = @call.run_batch(ops)
|
159
|
-
return unless assert_finished
|
160
|
-
unless batch_result.status.nil?
|
161
|
-
@call.trailing_metadata = batch_result.status.metadata
|
162
|
-
end
|
163
|
-
@call.status = batch_result.status
|
164
|
-
op_is_done
|
165
|
-
batch_result.check_status
|
166
|
-
end
|
167
|
-
|
168
160
|
# finished waits until a client call is completed.
|
169
161
|
#
|
170
162
|
# It blocks until the remote endpoint acknowledges by sending a status.
|
171
163
|
def finished
|
172
164
|
batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
|
173
|
-
|
174
|
-
|
165
|
+
attach_status_results_and_complete_call(batch_result)
|
166
|
+
end
|
167
|
+
|
168
|
+
def attach_status_results_and_complete_call(recv_status_batch_result)
|
169
|
+
unless recv_status_batch_result.status.nil?
|
170
|
+
@call.trailing_metadata = recv_status_batch_result.status.metadata
|
175
171
|
end
|
176
|
-
@call.status =
|
177
|
-
op_is_done
|
178
|
-
batch_result.check_status
|
172
|
+
@call.status = recv_status_batch_result.status
|
179
173
|
@call.close
|
174
|
+
op_is_done
|
175
|
+
|
176
|
+
# The RECV_STATUS in run_batch always succeeds
|
177
|
+
# Check the status for a bad status or failed run batch
|
178
|
+
recv_status_batch_result.check_status
|
180
179
|
end
|
181
180
|
|
182
181
|
# remote_send sends a request to the remote endpoint.
|
@@ -187,7 +186,8 @@ module GRPC
|
|
187
186
|
# @param marshalled [false, true] indicates if the object is already
|
188
187
|
# marshalled.
|
189
188
|
def remote_send(req, marshalled = false)
|
190
|
-
|
189
|
+
send_initial_metadata
|
190
|
+
GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}")
|
191
191
|
payload = marshalled ? req : @marshal.call(req)
|
192
192
|
@call.run_batch(SEND_MESSAGE => payload)
|
193
193
|
end
|
@@ -202,6 +202,7 @@ module GRPC
|
|
202
202
|
# list, mulitple metadata for its key are sent
|
203
203
|
def send_status(code = OK, details = '', assert_finished = false,
|
204
204
|
metadata: {})
|
205
|
+
send_initial_metadata
|
205
206
|
ops = {
|
206
207
|
SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, metadata)
|
207
208
|
}
|
@@ -210,6 +211,23 @@ module GRPC
|
|
210
211
|
nil
|
211
212
|
end
|
212
213
|
|
214
|
+
def server_unary_response(req, trailing_metadata: {},
|
215
|
+
code: Core::StatusCodes::OK, details: 'OK')
|
216
|
+
ops = {}
|
217
|
+
@send_initial_md_mutex.synchronize do
|
218
|
+
ops[SEND_INITIAL_METADATA] = @metadata_to_send unless @metadata_sent
|
219
|
+
@metadata_sent = true
|
220
|
+
end
|
221
|
+
|
222
|
+
payload = @marshal.call(req)
|
223
|
+
ops[SEND_MESSAGE] = payload
|
224
|
+
ops[SEND_STATUS_FROM_SERVER] = Struct::Status.new(
|
225
|
+
code, details, trailing_metadata)
|
226
|
+
ops[RECV_CLOSE_ON_SERVER] = nil
|
227
|
+
|
228
|
+
@call.run_batch(ops)
|
229
|
+
end
|
230
|
+
|
213
231
|
# remote_read reads a response from the remote endpoint.
|
214
232
|
#
|
215
233
|
# It blocks until the remote endpoint replies with a message or status.
|
@@ -224,9 +242,13 @@ module GRPC
|
|
224
242
|
@call.metadata = batch_result.metadata
|
225
243
|
@metadata_received = true
|
226
244
|
end
|
227
|
-
|
228
|
-
|
229
|
-
|
245
|
+
get_message_from_batch_result(batch_result)
|
246
|
+
end
|
247
|
+
|
248
|
+
def get_message_from_batch_result(recv_message_batch_result)
|
249
|
+
unless recv_message_batch_result.nil? ||
|
250
|
+
recv_message_batch_result.message.nil?
|
251
|
+
return @unmarshal.call(recv_message_batch_result.message)
|
230
252
|
end
|
231
253
|
GRPC.logger.debug('found nil; the final response has been sent')
|
232
254
|
nil
|
@@ -282,7 +304,6 @@ module GRPC
|
|
282
304
|
return enum_for(:each_remote_read_then_finish) unless block_given?
|
283
305
|
loop do
|
284
306
|
resp = remote_read
|
285
|
-
break if resp.is_a? Struct::Status # is an OK status
|
286
307
|
if resp.nil? # the last response was received, but not finished yet
|
287
308
|
finished
|
288
309
|
break
|
@@ -299,15 +320,25 @@ module GRPC
|
|
299
320
|
# a list, multiple metadata for its key are sent
|
300
321
|
# @return [Object] the response received from the server
|
301
322
|
def request_response(req, metadata: {})
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
323
|
+
ops = {
|
324
|
+
SEND_MESSAGE => @marshal.call(req),
|
325
|
+
SEND_CLOSE_FROM_CLIENT => nil,
|
326
|
+
RECV_INITIAL_METADATA => nil,
|
327
|
+
RECV_MESSAGE => nil,
|
328
|
+
RECV_STATUS_ON_CLIENT => nil
|
329
|
+
}
|
330
|
+
@send_initial_md_mutex.synchronize do
|
331
|
+
# Metadata might have already been sent if this is an operation view
|
332
|
+
unless @metadata_sent
|
333
|
+
ops[SEND_INITIAL_METADATA] = @metadata_to_send.merge!(metadata)
|
334
|
+
end
|
335
|
+
@metadata_sent = true
|
336
|
+
end
|
337
|
+
batch_result = @call.run_batch(ops)
|
338
|
+
|
339
|
+
@call.metadata = batch_result.metadata
|
340
|
+
attach_status_results_and_complete_call(batch_result)
|
341
|
+
get_message_from_batch_result(batch_result)
|
311
342
|
end
|
312
343
|
|
313
344
|
# client_streamer sends a stream of requests to a GRPC server, and
|
@@ -323,12 +354,20 @@ module GRPC
|
|
323
354
|
# a list, multiple metadata for its key are sent
|
324
355
|
# @return [Object] the response received from the server
|
325
356
|
def client_streamer(requests, metadata: {})
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
357
|
+
# Metadata might have already been sent if this is an operation view
|
358
|
+
merge_metadata_and_send_if_not_already_sent(metadata)
|
359
|
+
|
360
|
+
requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
|
361
|
+
batch_result = @call.run_batch(
|
362
|
+
SEND_CLOSE_FROM_CLIENT => nil,
|
363
|
+
RECV_INITIAL_METADATA => nil,
|
364
|
+
RECV_MESSAGE => nil,
|
365
|
+
RECV_STATUS_ON_CLIENT => nil
|
366
|
+
)
|
367
|
+
|
368
|
+
@call.metadata = batch_result.metadata
|
369
|
+
attach_status_results_and_complete_call(batch_result)
|
370
|
+
get_message_from_batch_result(batch_result)
|
332
371
|
rescue GRPC::Core::CallError => e
|
333
372
|
finished # checks for Cancelled
|
334
373
|
raise e
|
@@ -349,9 +388,18 @@ module GRPC
|
|
349
388
|
# a list, multiple metadata for its key are sent
|
350
389
|
# @return [Enumerator|nil] a response Enumerator
|
351
390
|
def server_streamer(req, metadata: {})
|
352
|
-
|
353
|
-
|
354
|
-
|
391
|
+
ops = {
|
392
|
+
SEND_MESSAGE => @marshal.call(req),
|
393
|
+
SEND_CLOSE_FROM_CLIENT => nil
|
394
|
+
}
|
395
|
+
@send_initial_md_mutex.synchronize do
|
396
|
+
# Metadata might have already been sent if this is an operation view
|
397
|
+
unless @metadata_sent
|
398
|
+
ops[SEND_INITIAL_METADATA] = @metadata_to_send.merge!(metadata)
|
399
|
+
end
|
400
|
+
@metadata_sent = true
|
401
|
+
end
|
402
|
+
@call.run_batch(ops)
|
355
403
|
replies = enum_for(:each_remote_read_then_finish)
|
356
404
|
return replies unless block_given?
|
357
405
|
replies.each { |r| yield r }
|
@@ -388,9 +436,13 @@ module GRPC
|
|
388
436
|
# a list, multiple metadata for its key are sent
|
389
437
|
# @return [Enumerator, nil] a response Enumerator
|
390
438
|
def bidi_streamer(requests, metadata: {}, &blk)
|
391
|
-
|
392
|
-
|
439
|
+
# Metadata might have already been sent if this is an operation view
|
440
|
+
merge_metadata_and_send_if_not_already_sent(metadata)
|
441
|
+
bd = BidiCall.new(@call,
|
442
|
+
@marshal,
|
443
|
+
@unmarshal,
|
393
444
|
metadata_received: @metadata_received)
|
445
|
+
|
394
446
|
bd.run_on_client(requests, @op_notifier, &blk)
|
395
447
|
end
|
396
448
|
|
@@ -406,8 +458,12 @@ module GRPC
|
|
406
458
|
#
|
407
459
|
# @param gen_each_reply [Proc] generates the BiDi stream replies
|
408
460
|
def run_server_bidi(gen_each_reply)
|
409
|
-
bd = BidiCall.new(@call,
|
410
|
-
|
461
|
+
bd = BidiCall.new(@call,
|
462
|
+
@marshal,
|
463
|
+
@unmarshal,
|
464
|
+
metadata_received: @metadata_received,
|
465
|
+
req_view: MultiReqView.new(self))
|
466
|
+
|
411
467
|
bd.run_on_server(gen_each_reply)
|
412
468
|
end
|
413
469
|
|
@@ -424,15 +480,32 @@ module GRPC
|
|
424
480
|
@op_notifier.notify(self)
|
425
481
|
end
|
426
482
|
|
483
|
+
# Add to the metadata that will be sent from the server.
|
484
|
+
# Fails if metadata has already been sent.
|
485
|
+
# Unused by client calls.
|
486
|
+
def merge_metadata_to_send(new_metadata = {})
|
487
|
+
@send_initial_md_mutex.synchronize do
|
488
|
+
fail('cant change metadata after already sent') if @metadata_sent
|
489
|
+
@metadata_to_send.merge!(new_metadata)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def merge_metadata_and_send_if_not_already_sent(new_metadata = {})
|
494
|
+
@send_initial_md_mutex.synchronize do
|
495
|
+
return if @metadata_sent
|
496
|
+
@metadata_to_send.merge!(new_metadata)
|
497
|
+
@call.run_batch(SEND_INITIAL_METADATA => @metadata_to_send)
|
498
|
+
@metadata_sent = true
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
427
502
|
private
|
428
503
|
|
429
504
|
# Starts the call if not already started
|
430
505
|
# @param metadata [Hash] metadata to be sent to the server. If a value is
|
431
506
|
# a list, multiple metadata for its key are sent
|
432
507
|
def start_call(metadata = {})
|
433
|
-
|
434
|
-
@metadata_tag = ActiveCall.client_invoke(@call, metadata)
|
435
|
-
@metadata_sent = true
|
508
|
+
merge_metadata_to_send(metadata) && send_initial_metadata
|
436
509
|
end
|
437
510
|
|
438
511
|
def self.view_class(*visible_methods)
|
@@ -450,12 +523,20 @@ module GRPC
|
|
450
523
|
# SingleReqView limits access to an ActiveCall's methods for use in server
|
451
524
|
# handlers that receive just one request.
|
452
525
|
SingleReqView = view_class(:cancelled?, :deadline, :metadata,
|
453
|
-
:output_metadata, :peer, :peer_cert
|
526
|
+
:output_metadata, :peer, :peer_cert,
|
527
|
+
:send_initial_metadata,
|
528
|
+
:metadata_to_send,
|
529
|
+
:merge_metadata_to_send,
|
530
|
+
:metadata_sent)
|
454
531
|
|
455
532
|
# MultiReqView limits access to an ActiveCall's methods for use in
|
456
533
|
# server client_streamer handlers.
|
457
534
|
MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg,
|
458
|
-
:each_remote_read, :metadata, :output_metadata
|
535
|
+
:each_remote_read, :metadata, :output_metadata,
|
536
|
+
:send_initial_metadata,
|
537
|
+
:metadata_to_send,
|
538
|
+
:merge_metadata_to_send,
|
539
|
+
:metadata_sent)
|
459
540
|
|
460
541
|
# Operation limits access to an ActiveCall's methods for use as
|
461
542
|
# a Operation on the client.
|