diff options
Diffstat (limited to 'src/ruby/lib')
-rw-r--r-- | src/ruby/lib/grpc.rb | 5 | ||||
-rw-r--r-- | src/ruby/lib/grpc/beefcake.rb | 62 | ||||
-rw-r--r-- | src/ruby/lib/grpc/core/event.rb (renamed from src/ruby/lib/grpc/event.rb) | 8 | ||||
-rw-r--r-- | src/ruby/lib/grpc/core/time_consts.rb (renamed from src/ruby/lib/grpc/time_consts.rb) | 61 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/active_call.rb | 43 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/bidi_call.rb | 17 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/client_stub.rb | 20 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/rpc_desc.rb | 9 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/rpc_server.rb | 25 | ||||
-rw-r--r-- | src/ruby/lib/grpc/generic/service.rb | 18 |
10 files changed, 177 insertions, 91 deletions
diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index 60a3b96527..1012a836b7 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -27,12 +27,13 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require 'grpc/event' +require 'grpc/beefcake' # extends beefcake require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' -require 'grpc/time_consts' require 'grpc/version' +require 'grpc/core/event' +require 'grpc/core/time_consts' # alias GRPC GRPC = Google::RPC diff --git a/src/ruby/lib/grpc/beefcake.rb b/src/ruby/lib/grpc/beefcake.rb new file mode 100644 index 0000000000..e8d7f0c2cd --- /dev/null +++ b/src/ruby/lib/grpc/beefcake.rb @@ -0,0 +1,62 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 'beefcake' + +# Re-open the beefcake message module to add a static encode +# +# This is a temporary measure while beefcake is used as the default proto +# library for developing grpc ruby. Once that changes to the official proto +# library this can be removed. It's necessary to allow the update the service +# module to assume a static encode method. +# +# TODO(temiola): remove me, once official code generation is available in protoc +module Beefcake + module Message + + # additional mixin module that adds static encode method when include + module StaticEncode + + # encodes o with its instance#encode method + def encode(o) + o.encode + end + + end + + # extend self.included in Beefcake::Message to include StaticEncode + def self.included(o) + o.extend StaticEncode + o.extend Dsl + o.extend Decode + o.send(:include, Encode) + end + + end +end diff --git a/src/ruby/lib/grpc/event.rb b/src/ruby/lib/grpc/core/event.rb index c108cd4c1e..29486763d5 100644 --- a/src/ruby/lib/grpc/event.rb +++ b/src/ruby/lib/grpc/core/event.rb @@ -29,9 +29,11 @@ module Google module RPC - class Event # Add an inspect method to C-defined Event class. - def inspect - '<%s: type:%s, tag:%s result:%s>' % [self.class, type, tag, result] + module Core + class Event # Add an inspect method to C-defined Event class. + def inspect + '<%s: type:%s, tag:%s result:%s>' % [self.class, type, tag, result] + end end end end diff --git a/src/ruby/lib/grpc/time_consts.rb b/src/ruby/lib/grpc/core/time_consts.rb index 2cbab5d965..52e4c3f9b9 100644 --- a/src/ruby/lib/grpc/time_consts.rb +++ b/src/ruby/lib/grpc/core/time_consts.rb @@ -31,39 +31,42 @@ require 'grpc' module Google module RPC - module TimeConsts # re-opens a module in the C extension. + module Core - # Converts a time delta to an absolute deadline. - # - # Assumes timeish is a relative time, and converts its to an absolute, - # with following exceptions: - # - # * if timish is one of the TimeConsts.TimeSpec constants the value is - # preserved. - # * timish < 0 => TimeConsts.INFINITE_FUTURE - # * timish == 0 => TimeConsts.ZERO - # - # @param timeish [Number|TimeSpec] - # @return timeish [Number|TimeSpec] - def from_relative_time(timeish) - if timeish.is_a?TimeSpec - timeish - elsif timeish.nil? - TimeConsts::ZERO - elsif !timeish.is_a?Numeric - raise TypeError('Cannot make an absolute deadline from %s', - timeish.inspect) - elsif timeish < 0 - TimeConsts::INFINITE_FUTURE - elsif timeish == 0 - TimeConsts::ZERO - else !timeish.nil? - Time.now + timeish + module TimeConsts # re-opens a module in the C extension. + + # Converts a time delta to an absolute deadline. + # + # Assumes timeish is a relative time, and converts its to an absolute, + # with following exceptions: + # + # * if timish is one of the TimeConsts.TimeSpec constants the value is + # preserved. + # * timish < 0 => TimeConsts.INFINITE_FUTURE + # * timish == 0 => TimeConsts.ZERO + # + # @param timeish [Number|TimeSpec] + # @return timeish [Number|TimeSpec] + def from_relative_time(timeish) + if timeish.is_a?TimeSpec + timeish + elsif timeish.nil? + TimeConsts::ZERO + elsif !timeish.is_a?Numeric + raise TypeError('Cannot make an absolute deadline from %s', + timeish.inspect) + elsif timeish < 0 + TimeConsts::INFINITE_FUTURE + elsif timeish == 0 + TimeConsts::ZERO + else !timeish.nil? + Time.now + timeish + end end - end - module_function :from_relative_time + module_function :from_relative_time + end end end end diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index d987b3966f..de35f278a1 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -40,8 +40,9 @@ module GRPC # The ActiveCall class provides simple methods for sending marshallable # data to a call class ActiveCall - include CompletionType - include StatusCodes + include Core::CompletionType + include Core::StatusCodes + include Core::TimeConsts attr_reader(:deadline) # client_start_invoke begins a client invocation. @@ -55,15 +56,15 @@ module GRPC # @param q [CompletionQueue] used to wait for INVOKE_ACCEPTED # @param deadline [Fixnum,TimeSpec] the deadline for INVOKE_ACCEPTED def self.client_start_invoke(call, q, deadline) - raise ArgumentError.new('not a call') unless call.is_a?Call - if !q.is_a?CompletionQueue + raise ArgumentError.new('not a call') unless call.is_a?Core::Call + if !q.is_a?Core::CompletionQueue raise ArgumentError.new('not a CompletionQueue') end invoke_accepted, client_metadata_read = Object.new, Object.new finished_tag = Object.new call.start_invoke(q, invoke_accepted, client_metadata_read, finished_tag) # wait for the invocation to be accepted - ev = q.pluck(invoke_accepted, TimeConsts::INFINITE_FUTURE) + ev = q.pluck(invoke_accepted, INFINITE_FUTURE) raise OutOfTime if ev.nil? finished_tag end @@ -93,8 +94,8 @@ module GRPC # @param started [true|false] (default true) indicates if the call has begun def initialize(call, q, marshal, unmarshal, deadline, finished_tag: nil, started: true) - raise ArgumentError.new('not a call') unless call.is_a?Call - if !q.is_a?CompletionQueue + raise ArgumentError.new('not a call') unless call.is_a?Core::Call + if !q.is_a?Core::CompletionQueue raise ArgumentError.new('not a CompletionQueue') end @call = call @@ -178,11 +179,11 @@ module GRPC # FINISHED. def writes_done(assert_finished=true) @call.writes_done(self) - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(self, INFINITE_FUTURE) assert_event_type(ev.type, FINISH_ACCEPTED) logger.debug("Writes done: waiting for finish? #{assert_finished}") if assert_finished - ev = @cq.pluck(@finished_tag, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) raise "unexpected event: #{ev.inspect}" if ev.nil? return @call.status end @@ -193,9 +194,9 @@ module GRPC # It blocks until the remote endpoint acknowledges by sending a FINISHED # event. def finished - ev = @cq.pluck(@finished_tag, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) raise "unexpected event: #{ev.inspect}" unless ev.type == FINISHED - if ev.result.code != StatusCodes::OK + if ev.result.code != Core::StatusCodes::OK raise BadStatus.new(ev.result.code, ev.result.details) end res = ev.result @@ -223,11 +224,11 @@ module GRPC else payload = @marshal.call(req) end - @call.start_write(ByteBuffer.new(payload), self) + @call.start_write(Core::ByteBuffer.new(payload), self) # call queue#pluck, and wait for WRITE_ACCEPTED, so as not to return # until the flow control allows another send on this call. - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(self, INFINITE_FUTURE) assert_event_type(ev.type, WRITE_ACCEPTED) ev = nil end @@ -240,8 +241,8 @@ module GRPC # FINISHED. def send_status(code=OK, details='', assert_finished=false) assert_queue_is_ready - @call.start_write_status(Status.new(code, details), self) - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + @call.start_write_status(Core::Status.new(code, details), self) + ev = @cq.pluck(self, INFINITE_FUTURE) assert_event_type(ev.type, FINISH_ACCEPTED) logger.debug("Status sent: #{code}:'#{details}'") if assert_finished @@ -257,7 +258,7 @@ module GRPC # FINISHED, it returns nil if the status is OK, otherwise raising BadStatus def remote_read @call.start_read(self) - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(self, INFINITE_FUTURE) assert_event_type(ev.type, READ) logger.debug("received req: #{ev.result.inspect}") if !ev.result.nil? @@ -291,7 +292,7 @@ module GRPC return enum_for(:each_remote_read) if !block_given? loop do resp = remote_read() - break if resp.is_a?Status # this will be an OK status, bad statii raise + break if resp.is_a?Core::Status # is an OK status, bad statii raise break if resp.nil? # the last response was received yield resp end @@ -321,7 +322,7 @@ module GRPC return enum_for(:each_remote_read_then_finish) if !block_given? loop do resp = remote_read - break if resp.is_a?Status # this will be an OK status, bad statii raise + break if resp.is_a?Core::Status # is an OK status, bad statii raise if resp.nil? # the last response was received, but not finished yet finished break @@ -339,7 +340,7 @@ module GRPC remote_send(req) writes_done(false) response = remote_read - if !response.is_a?(Status) # finish if status not yet received + if !response.is_a?(Core::Status) # finish if status not yet received finished end response @@ -360,7 +361,7 @@ module GRPC requests.each { |r| remote_send(r) } writes_done(false) response = remote_read - if !response.is_a?(Status) # finish if status not yet received + if !response.is_a?(Core::Status) # finish if status not yet received finished end response @@ -472,7 +473,7 @@ module GRPC # shutdown. def assert_queue_is_ready begin - ev = @cq.pluck(self, TimeConsts::ZERO) + ev = @cq.pluck(self, ZERO) raise "unexpected event #{ev.inspect}" unless ev.nil? rescue OutOfTime # expected, nothing should be on the queue and the deadline was ZERO, diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index a3566e1118..91ceaa90e5 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -35,8 +35,9 @@ module GRPC # The BiDiCall class orchestrates exection of a BiDi stream on a client or # server. class BidiCall - include CompletionType - include StatusCodes + include Core::CompletionType + include Core::StatusCodes + include Core::TimeConsts # Creates a BidiCall. # @@ -59,8 +60,8 @@ module GRPC # @param deadline [Fixnum] the deadline for the call to complete # @param finished_tag [Object] the object used as the call's finish tag, def initialize(call, q, marshal, unmarshal, deadline, finished_tag) - raise ArgumentError.new('not a call') unless call.is_a?Call - if !q.is_a?CompletionQueue + raise ArgumentError.new('not a call') unless call.is_a?Core::Call + if !q.is_a?Core::CompletionQueue raise ArgumentError.new('not a CompletionQueue') end @call = call @@ -210,7 +211,7 @@ module GRPC # send the payload payload = @marshal.call(req) - @call.start_write(ByteBuffer.new(payload), self) + @call.start_write(Core::ByteBuffer.new(payload), self) logger.debug("rwloop: sent payload #{req.inspect}") in_write = true return [in_write, done_writing] @@ -259,10 +260,10 @@ module GRPC logger.debug('waiting for another event') if in_write or !done_reading or !pre_finished logger.debug('waiting for another event') - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(self, INFINITE_FUTURE) elsif !finished logger.debug('waiting for another event') - ev = @cq.pluck(@finish_tag, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) else next # no events to wait on, but not done writing end @@ -270,7 +271,7 @@ module GRPC break if done_writing and done_reading if in_write or !done_reading logger.debug('waiting for another event') - ev = @cq.pluck(self, TimeConsts::INFINITE_FUTURE) + ev = @cq.pluck(self, INFINITE_FUTURE) else next # no events to wait on, but not done writing end diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index fee31e3353..144f9d93ec 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -35,7 +35,7 @@ module GRPC # ClientStub represents an endpoint used to send requests to GRPC servers. class ClientStub - include StatusCodes + include Core::StatusCodes # Default deadline is 5 seconds. DEFAULT_DEADLINE = 5 @@ -62,23 +62,29 @@ module GRPC # when present, this is the default deadline used for calls # # @param host [String] the host the stub connects to - # @param q [TaggedCompletionQueue] used to wait for events - # @param channel_override [Channel] a pre-created channel + # @param q [Core::CompletionQueue] used to wait for events + # @param channel_override [Core::Channel] a pre-created channel # @param deadline [Number] the default deadline to use in requests + # @param creds [Core::Credentials] secures and/or authenticates the channel # @param kw [KeywordArgs] the channel arguments def initialize(host, q, channel_override:nil, deadline:DEFAULT_DEADLINE, + creds:nil, **kw) - if !q.is_a?CompletionQueue + if !q.is_a?Core::CompletionQueue raise ArgumentError.new('not a CompletionQueue') end @host = host if !channel_override.nil? ch = channel_override - raise ArgumentError.new('not a Channel') unless ch.is_a?(Channel) + raise ArgumentError.new('not a Channel') unless ch.is_a?(Core::Channel) + elsif creds.nil? + ch = Core::Channel.new(host, kw) + elsif !creds.is_a?(Core::Credentials) + raise ArgumentError.new('not a Credentials') else - ch = Channel.new(host, **kw) + ch = Core::Channel.new(host, kw, creds) end @deadline = deadline @@ -347,7 +353,7 @@ module GRPC # @param unmarshal [Function] f(string)->obj that unmarshals responses # @param deadline [TimeConst] def new_active_call(ch, marshal, unmarshal, deadline=nil) - absolute_deadline = TimeConsts.from_relative_time(deadline) + absolute_deadline = Core::TimeConsts.from_relative_time(deadline) call = @ch.create_call(ch, @host, absolute_deadline) ActiveCall.new(call, @queue, marshal, unmarshal, absolute_deadline, started:false) diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb index 43b4d4ffc6..eef886a72f 100644 --- a/src/ruby/lib/grpc/generic/rpc_desc.rb +++ b/src/ruby/lib/grpc/generic/rpc_desc.rb @@ -34,6 +34,7 @@ module GRPC # RpcDesc is a Descriptor of an RPC method. class RpcDesc < Struct.new(:name, :input, :output, :marshal_method, :unmarshal_method) + include Core::StatusCodes # Used to wrap a message class to indicate that it needs to be streamed. class Stream @@ -46,7 +47,7 @@ module GRPC # @return [Proc] { |instance| marshalled(instance) } def marshal_proc - Proc.new { |o| o.method(marshal_method).call.to_s } + Proc.new { |o| o.class.method(marshal_method).call(o).to_s } end # @param [:input, :output] target determines whether to produce the an @@ -82,7 +83,7 @@ module GRPC else # is a bidi_stream active_call.run_server_bidi(mth) end - send_status(active_call, StatusCodes::OK, 'OK') + send_status(active_call, OK, 'OK') active_call.finished rescue BadStatus => e # this is raised by handlers that want GRPC to send an application @@ -97,7 +98,7 @@ module GRPC # This is raised when active_call#method.call exceeeds the deadline # event. Send a status of deadline exceeded logger.warn("late call: #{active_call}") - send_status(active_call, StatusCodes::DEADLINE_EXCEEDED, 'late') + send_status(active_call, DEADLINE_EXCEEDED, 'late') rescue EventError => e # This is raised by GRPC internals but should rarely, if ever happen. # Log it, but don't notify the other endpoint.. @@ -107,7 +108,7 @@ module GRPC # Send back a UNKNOWN status to the client logger.warn("failed handler: #{active_call}; sending status:UNKNOWN") logger.warn(e) - send_status(active_call, StatusCodes::UNKNOWN, 'no reason given') + send_status(active_call, UNKNOWN, 'no reason given') end end diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index e6efdc32c1..ebbf3f9780 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -38,7 +38,8 @@ module GRPC # RpcServer hosts a number of services and makes them available on the # network. class RpcServer - include CompletionType + include Core::CompletionType + include Core::TimeConsts extend ::Forwardable def_delegators :@server, :add_http2_port @@ -57,7 +58,7 @@ module GRPC # instance, however other arbitrary are allowed and when present are used # to configure the listeninng connection set up by the RpcServer. # - # * server_override: which if passed must be a [GRPC::Server]. When + # * server_override: which if passed must be a [GRPC::Core::Server]. When # present. # # * poll_period: when present, the server polls for new events with this @@ -70,30 +71,38 @@ module GRPC # completion_queue that the server uses to receive network events, # otherwise its creates a new instance itself # + # * creds: [GRPC::Core::ServerCredentials] + # the credentials used to secure the server + # # * max_waiting_requests: the maximum number of requests that are not # being handled to allow. When this limit is exceeded, the server responds # with not available to new requests def initialize(pool_size:DEFAULT_POOL_SIZE, max_waiting_requests:DEFAULT_MAX_WAITING_REQUESTS, - poll_period:TimeConsts::INFINITE_FUTURE, + poll_period:INFINITE_FUTURE, completion_queue_override:nil, + creds:nil, server_override:nil, **kw) if !completion_queue_override.nil? cq = completion_queue_override - if !cq.is_a?(CompletionQueue) + if !cq.is_a?(Core::CompletionQueue) raise ArgumentError.new('not a CompletionQueue') end else - cq = CompletionQueue.new + cq = Core::CompletionQueue.new end @cq = cq if !server_override.nil? srv = server_override - raise ArgumentError.new('not a Server') unless srv.is_a?(Server) + raise ArgumentError.new('not a Server') unless srv.is_a?(Core::Server) + elsif creds.nil? + srv = Core::Server.new(@cq, kw) + elsif !creds.is_a?(Core::ServerCredentials) + raise ArgumentError.new('not a ServerCredentials') else - srv = Server.new(@cq, **kw) + srv = Core::Server.new(@cq, kw, creds) end @server = srv @@ -236,7 +245,7 @@ module GRPC # Accept the call. This is necessary even if a status is to be sent back # immediately finished_tag = Object.new - call_queue = CompletionQueue.new + call_queue = Core::CompletionQueue.new call.accept(call_queue, finished_tag) # Send UNAVAILABLE if there are too many unprocessed jobs diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb index 1a3d0dc63e..05bb0af809 100644 --- a/src/ruby/lib/grpc/generic/service.rb +++ b/src/ruby/lib/grpc/generic/service.rb @@ -88,12 +88,12 @@ module GRPC # - unmarshal_class method must be a class method on the serializable # message type that takes a string (byte stream) and produces and object # - # - marshal_instance_method is called on a serializable message instance + # - marshal_class_method is called on a serializable message instance # and produces a serialized string. # # The Dsl verifies that the types in the descriptor have both the # unmarshal and marshal methods. - attr_writer(:marshal_instance_method, :unmarshal_class_method) + attr_writer(:marshal_class_method, :unmarshal_class_method) attr_accessor(:service_name) # Adds an RPC spec. @@ -113,7 +113,7 @@ module GRPC assert_can_marshal(input) assert_can_marshal(output) rpc_descs[name] = RpcDesc.new(name, input, output, - marshal_instance_method, + marshal_class_method, unmarshal_class_method) end @@ -125,8 +125,8 @@ module GRPC end # the name of the instance method used to marshal events to a byte stream. - def marshal_instance_method - @marshal_instance_method ||= :marshal + def marshal_class_method + @marshal_class_method ||= :marshal end # the name of the class method used to unmarshal from a byte stream. @@ -144,9 +144,9 @@ module GRPC raise ArgumentError, "#{cls} needs #{cls}.#{mth}" end - mth = marshal_instance_method - if !cls.instance_methods.include?(mth) - raise ArgumentError, "#{cls} needs #{cls}.new.#{mth}" + mth = marshal_class_method + if !cls.methods.include?(mth) + raise ArgumentError, "#{cls} needs #{cls}.#{mth}" end end @@ -173,7 +173,7 @@ module GRPC # @param kw [KeywordArgs] the channel arguments, plus any optional # args for configuring the client's channel def initialize(host, **kw) - super(host, CompletionQueue.new, **kw) + super(host, Core::CompletionQueue.new, **kw) end # Used define_method to add a method for each rpc_desc. Each method |