|
|
@ -58,7 +58,7 @@ module GRPC |
|
|
|
include Core::TimeConsts |
|
|
|
include Core::TimeConsts |
|
|
|
include Core::CallOps |
|
|
|
include Core::CallOps |
|
|
|
extend Forwardable |
|
|
|
extend Forwardable |
|
|
|
attr_reader(:deadline) |
|
|
|
attr_reader :deadline, :metadata_sent, :metadata_to_send |
|
|
|
def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=, |
|
|
|
def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=, |
|
|
|
:peer, :peer_cert, :trailing_metadata |
|
|
|
:peer, :peer_cert, :trailing_metadata |
|
|
|
|
|
|
|
|
|
|
@ -101,7 +101,7 @@ module GRPC |
|
|
|
# @param metadata_received [true|false] indicates if metadata has already |
|
|
|
# @param metadata_received [true|false] indicates if metadata has already |
|
|
|
# been received. Should always be true for server calls |
|
|
|
# been received. Should always be true for server calls |
|
|
|
def initialize(call, marshal, unmarshal, deadline, started: true, |
|
|
|
def initialize(call, marshal, unmarshal, deadline, started: true, |
|
|
|
metadata_received: false) |
|
|
|
metadata_received: false, metadata_to_send: nil) |
|
|
|
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call |
|
|
|
fail(TypeError, '!Core::Call') unless call.is_a? Core::Call |
|
|
|
@call = call |
|
|
|
@call = call |
|
|
|
@deadline = deadline |
|
|
|
@deadline = deadline |
|
|
@ -110,6 +110,20 @@ module GRPC |
|
|
|
@metadata_received = metadata_received |
|
|
|
@metadata_received = metadata_received |
|
|
|
@metadata_sent = started |
|
|
|
@metadata_sent = started |
|
|
|
@op_notifier = nil |
|
|
|
@op_notifier = nil |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fail(ArgumentError, 'Already sent md') if started && metadata_to_send |
|
|
|
|
|
|
|
@metadata_to_send = metadata_to_send || {} unless started |
|
|
|
|
|
|
|
@send_initial_md_mutex = Mutex.new |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Sends the initial metadata that has yet to be sent. |
|
|
|
|
|
|
|
# Does nothing if metadata has already been sent for this call. |
|
|
|
|
|
|
|
def send_initial_metadata |
|
|
|
|
|
|
|
@send_initial_md_mutex.synchronize do |
|
|
|
|
|
|
|
return if @metadata_sent |
|
|
|
|
|
|
|
@metadata_tag = ActiveCall.client_invoke(@call, @metadata_to_send) |
|
|
|
|
|
|
|
@metadata_sent = true |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
# output_metadata are provides access to hash that can be used to |
|
|
|
# output_metadata are provides access to hash that can be used to |
|
|
@ -187,7 +201,7 @@ module GRPC |
|
|
|
# @param marshalled [false, true] indicates if the object is already |
|
|
|
# @param marshalled [false, true] indicates if the object is already |
|
|
|
# marshalled. |
|
|
|
# marshalled. |
|
|
|
def remote_send(req, marshalled = false) |
|
|
|
def remote_send(req, marshalled = false) |
|
|
|
# TODO(murgatroid99): ensure metadata was sent |
|
|
|
send_initial_metadata |
|
|
|
GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}") |
|
|
|
GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}") |
|
|
|
payload = marshalled ? req : @marshal.call(req) |
|
|
|
payload = marshalled ? req : @marshal.call(req) |
|
|
|
@call.run_batch(SEND_MESSAGE => payload) |
|
|
|
@call.run_batch(SEND_MESSAGE => payload) |
|
|
@ -203,6 +217,7 @@ module GRPC |
|
|
|
# list, mulitple metadata for its key are sent |
|
|
|
# list, mulitple metadata for its key are sent |
|
|
|
def send_status(code = OK, details = '', assert_finished = false, |
|
|
|
def send_status(code = OK, details = '', assert_finished = false, |
|
|
|
metadata: {}) |
|
|
|
metadata: {}) |
|
|
|
|
|
|
|
send_initial_metadata |
|
|
|
ops = { |
|
|
|
ops = { |
|
|
|
SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, metadata) |
|
|
|
SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, metadata) |
|
|
|
} |
|
|
|
} |
|
|
@ -303,7 +318,7 @@ module GRPC |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# @return [Object] the response received from the server |
|
|
|
# @return [Object] the response received from the server |
|
|
|
def request_response(req, metadata: {}) |
|
|
|
def request_response(req, metadata: {}) |
|
|
|
start_call(metadata) |
|
|
|
merge_metadata_to_send(metadata) && send_initial_metadata |
|
|
|
remote_send(req) |
|
|
|
remote_send(req) |
|
|
|
writes_done(false) |
|
|
|
writes_done(false) |
|
|
|
response = remote_read |
|
|
|
response = remote_read |
|
|
@ -327,7 +342,7 @@ module GRPC |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# @return [Object] the response received from the server |
|
|
|
# @return [Object] the response received from the server |
|
|
|
def client_streamer(requests, metadata: {}) |
|
|
|
def client_streamer(requests, metadata: {}) |
|
|
|
start_call(metadata) |
|
|
|
merge_metadata_to_send(metadata) && send_initial_metadata |
|
|
|
requests.each { |r| remote_send(r) } |
|
|
|
requests.each { |r| remote_send(r) } |
|
|
|
writes_done(false) |
|
|
|
writes_done(false) |
|
|
|
response = remote_read |
|
|
|
response = remote_read |
|
|
@ -353,7 +368,7 @@ module GRPC |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# @return [Enumerator|nil] a response Enumerator |
|
|
|
# @return [Enumerator|nil] a response Enumerator |
|
|
|
def server_streamer(req, metadata: {}) |
|
|
|
def server_streamer(req, metadata: {}) |
|
|
|
start_call(metadata) |
|
|
|
merge_metadata_to_send(metadata) && send_initial_metadata |
|
|
|
remote_send(req) |
|
|
|
remote_send(req) |
|
|
|
writes_done(false) |
|
|
|
writes_done(false) |
|
|
|
replies = enum_for(:each_remote_read_then_finish) |
|
|
|
replies = enum_for(:each_remote_read_then_finish) |
|
|
@ -392,9 +407,12 @@ module GRPC |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# @return [Enumerator, nil] a response Enumerator |
|
|
|
# @return [Enumerator, nil] a response Enumerator |
|
|
|
def bidi_streamer(requests, metadata: {}, &blk) |
|
|
|
def bidi_streamer(requests, metadata: {}, &blk) |
|
|
|
start_call(metadata) |
|
|
|
merge_metadata_to_send(metadata) && send_initial_metadata |
|
|
|
bd = BidiCall.new(@call, @marshal, @unmarshal, |
|
|
|
bd = BidiCall.new(@call, |
|
|
|
|
|
|
|
@marshal, |
|
|
|
|
|
|
|
@unmarshal, |
|
|
|
metadata_received: @metadata_received) |
|
|
|
metadata_received: @metadata_received) |
|
|
|
|
|
|
|
|
|
|
|
bd.run_on_client(requests, @op_notifier, &blk) |
|
|
|
bd.run_on_client(requests, @op_notifier, &blk) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
@ -410,8 +428,12 @@ module GRPC |
|
|
|
# |
|
|
|
# |
|
|
|
# @param gen_each_reply [Proc] generates the BiDi stream replies |
|
|
|
# @param gen_each_reply [Proc] generates the BiDi stream replies |
|
|
|
def run_server_bidi(gen_each_reply) |
|
|
|
def run_server_bidi(gen_each_reply) |
|
|
|
bd = BidiCall.new(@call, @marshal, @unmarshal, |
|
|
|
bd = BidiCall.new(@call, |
|
|
|
metadata_received: @metadata_received) |
|
|
|
@marshal, |
|
|
|
|
|
|
|
@unmarshal, |
|
|
|
|
|
|
|
metadata_received: @metadata_received, |
|
|
|
|
|
|
|
req_view: MultiReqView.new(self)) |
|
|
|
|
|
|
|
|
|
|
|
bd.run_on_server(gen_each_reply) |
|
|
|
bd.run_on_server(gen_each_reply) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
@ -428,15 +450,23 @@ module GRPC |
|
|
|
@op_notifier.notify(self) |
|
|
|
@op_notifier.notify(self) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add to the metadata that will be sent from the server. |
|
|
|
|
|
|
|
# Fails if metadata has already been sent. |
|
|
|
|
|
|
|
# Unused by client calls. |
|
|
|
|
|
|
|
def merge_metadata_to_send(new_metadata = {}) |
|
|
|
|
|
|
|
@send_initial_md_mutex.synchronize do |
|
|
|
|
|
|
|
fail('cant change metadata after already sent') if @metadata_sent |
|
|
|
|
|
|
|
@metadata_to_send.merge!(new_metadata) |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
private |
|
|
|
private |
|
|
|
|
|
|
|
|
|
|
|
# Starts the call if not already started |
|
|
|
# Starts the call if not already started |
|
|
|
# @param metadata [Hash] metadata to be sent to the server. If a value is |
|
|
|
# @param metadata [Hash] metadata to be sent to the server. If a value is |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
# a list, multiple metadata for its key are sent |
|
|
|
def start_call(metadata = {}) |
|
|
|
def start_call(metadata = {}) |
|
|
|
return if @metadata_sent |
|
|
|
merge_metadata_to_send(metadata) && send_initial_metadata |
|
|
|
@metadata_tag = ActiveCall.client_invoke(@call, metadata) |
|
|
|
|
|
|
|
@metadata_sent = true |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
def self.view_class(*visible_methods) |
|
|
|
def self.view_class(*visible_methods) |
|
|
@ -454,12 +484,20 @@ module GRPC |
|
|
|
# SingleReqView limits access to an ActiveCall's methods for use in server |
|
|
|
# SingleReqView limits access to an ActiveCall's methods for use in server |
|
|
|
# handlers that receive just one request. |
|
|
|
# handlers that receive just one request. |
|
|
|
SingleReqView = view_class(:cancelled?, :deadline, :metadata, |
|
|
|
SingleReqView = view_class(:cancelled?, :deadline, :metadata, |
|
|
|
:output_metadata, :peer, :peer_cert) |
|
|
|
:output_metadata, :peer, :peer_cert, |
|
|
|
|
|
|
|
:send_initial_metadata, |
|
|
|
|
|
|
|
:metadata_to_send, |
|
|
|
|
|
|
|
:merge_metadata_to_send, |
|
|
|
|
|
|
|
:metadata_sent) |
|
|
|
|
|
|
|
|
|
|
|
# MultiReqView limits access to an ActiveCall's methods for use in |
|
|
|
# MultiReqView limits access to an ActiveCall's methods for use in |
|
|
|
# server client_streamer handlers. |
|
|
|
# server client_streamer handlers. |
|
|
|
MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg, |
|
|
|
MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg, |
|
|
|
:each_remote_read, :metadata, :output_metadata) |
|
|
|
:each_remote_read, :metadata, :output_metadata, |
|
|
|
|
|
|
|
:send_initial_metadata, |
|
|
|
|
|
|
|
:metadata_to_send, |
|
|
|
|
|
|
|
:merge_metadata_to_send, |
|
|
|
|
|
|
|
:metadata_sent) |
|
|
|
|
|
|
|
|
|
|
|
# Operation limits access to an ActiveCall's methods for use as |
|
|
|
# Operation limits access to an ActiveCall's methods for use as |
|
|
|
# a Operation on the client. |
|
|
|
# a Operation on the client. |
|
|
|