module Yrpc module Controllers class ServiceBinder ## #未来可能会有一些desc 的 拓展,先预留一个肉便器类。 # class BoundDesc < SimpleDelegator; end #初始化。。没什么好解释的 def initialize(service) @service = service end # 通过controller绑定所有的方法 def bind!(controller) rpc_methods.each { |name, desc| bind_method(controller, name, desc) } end def rpc_desc(request_method) @service.rpc_descs[request_method] end private #打开类并且进行一个方法define,返回给这个方法打call。这里要注意的是request 会以参数形式构造进controller #这里也涉及到stream 类型。 def bind_method(controller, method_name, desc) method_desc = method_name.to_s.to_sym method_key = method_name.to_s.underscore.to_sym current_desc = rpc_desc(method_desc) service_ref = @service @service.class_eval do if desc.request_response? define_method(method_key) do |message, active_call| c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc) begin c.call(method_key) rescue => e p method_key p e.backtrace_locations desc && desc.output ? desc.output.new(status: {code: e.respond_to?(:code) ? e.code : Yrpc::Response::Code::ERROR , message: e.message}) : (raise e) end end elsif desc.client_streamer? define_method(method_key) do |active_call| c = controller.new(method_key: method_key, service: service_ref, message: proc { |&block| active_call.each_remote_read(&block) }, active_call: active_call, rpc_desc: desc) begin c.call(method_key) rescue => e desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR, message: e.message}) : (raise e) end end elsif desc.server_streamer? define_method(method_key) do |message, active_call, &block| c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc) begin c.call(method_key) rescue => e desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR , message: e.message}) : (raise e) end end else # bidi define_method(method_key) do |messages, active_call, &block| c = controller.new(method_key: method_key, service: service_ref, message: messages, active_call: active_call, rpc_desc: desc) begin c.call(method_key) rescue => e desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR, message: e.message}) : (raise e) end end end end end ## # 讲方法都代理到boundDesc 上 # def rpc_methods @service.rpc_descs.map { |rd| BoundDesc.new(rd) } end end end end