class PipeRpc::Request; end module PipeRpc class Client::Request < Request def initialize(hub, request) @hub = hub request[:arguments] = arguments_to_server_ids(request[:arguments]) super request # discard first three entries mentioning Client::Request#initialize, # Client::Request.new and Client#method_missing in stacktrace @stacktrace = Kernel.respond_to?(:caller) ? Kernel.caller(3).to_a : [] @result = Result.new(self) end attr_reader :hub, :stacktrace, :result def id=(id) raise 'id already set' if @id @id = id end def id @id or raise 'id not set' end def arguments_to_server_ids(arguments) deep_map(arguments) do |value| if value.respond_to? :__rpc_server_id__ # is a client value.__rpc_server_id__ elsif value.respond_to? :to_rpc_server_id # is a servable @hub.servers.add(value) value.to_rpc_server_id else value end end end def deep_map(object, &mapper) case object when Hash then object.map{ |k, v| [k, deep_map(v, &mapper)] }.to_h when Array then object.map{ |item| deep_map(item, &mapper) } else yield object end end end end