class EmFarcall::Endpoint

Endpoint that run in the reactor thread of the EM. Eventmachine should run by the time of creation of the endpoint. All the methods can be called from any thread, not only EM's reactor thread.

As the eventmachine callback paradigm is completely different from the threaded paradigm of the Farcall, that runs pretty well under JRuby and in multithreaded MRI, we provide compatible but different endpoint to run under EM.

Its main difference is that there is no sync_call, instead, calling remote commands from the endpoint and/ot interface can provide blocks that are called when the remote is executed.

The EM version of the endpoint works with any 2 EM:C:Channels.

Attributes

provider[RW]

Set or get provider instance. When provider is set, its public methods are called by the remote and any possible exception are passed back to caller party. You can use any ruby class instance everything will work, operators, indexes[] and like.

Public Class Methods

new(input_channel, output_channel, errback=nil, provider: nil) click to toggle source

Create new endpoint to work with input and output channels

@param [EM::Channel] input_channel @param [EM::Channel] output_channel

# File lib/farcall/em_farcall.rb, line 40
def initialize(input_channel, output_channel, errback=nil, provider: nil)
  EM.schedule {
    @input, @output, @errback = input_channel, output_channel, errback
    @trace                    = false
    @in_serial                = @out_serial = 0
    @callbacks                = {}
    @handlers                 = {}
    @unnamed_handler          = -> (name, *args, **kwargs) {
      raise NoMethodError, "method does not exist: #{name}"
    }
    @input.subscribe { |data|
      process_input(data)
    }
    if provider
      @provider         = provider
      provider.endpoint = self
    end
  }
end

Public Instance Methods

call(name, *args, **kwargs, &block) click to toggle source

Call the remote method with specified name and arguments calling block when done. Returns immediately a {Farcall::Promise} instance which could be used to control remote procedure invocation result asynchronously and effective.

Also, if block is provided, it will be called when the remote will be called and possibly return some data. It receives single object paramter with two fields: result.error and result.result. It is also possible to use returned {Farcall::Promise} instance to set multiple callbacks with ease. Promise callbacks are called after the block.

`result.error` is not nil when the remote raised error, then `error` and `error.text` are set accordingly.

if error is nil then result.result receives any return data from the remote method.

for example:

endpoint.call( 'some_func', 10, 20) { |done|
   if done.error
     puts "Remote error class: #{done.error[:class]}: #{done.error.text}"
   else
     puts "Remote returned #{done.result}"
}

@param name [String] remote method name @return [Promise] object that call be used to set multiple handlers on success

or fail event. {Farcall::Promise#success} receives remote return result on
success and {Farcall::Promise#fail} receives error object.
# File lib/farcall/em_farcall.rb, line 92
def call(name, *args, **kwargs, &block)
  promise = Farcall::Promise.new
  EM.schedule {
    @callbacks[@in_serial] = -> (result) {
      block.call(result) if block != nil
      if result.error
        promise.set_fail result.error
      else
        promise.set_success result.result
      end
    }
    send_block cmd: name, args: args, kwargs: kwargs
  }
  promise
end
close() click to toggle source

Close the endpoint

Calls superclass method
# File lib/farcall/em_farcall.rb, line 109
def close
  super
end
error(text) click to toggle source

Report error via errback and the endpoint

# File lib/farcall/em_farcall.rb, line 114
def error text
  STDERR.puts "farcall ws server error #{text}"
  EM.schedule {
    @errback.call(text) if @errback
    close
  }
end
on(name, &block) click to toggle source

Set handler to perform the named command. Block will be called when the remote party calls with parameters passed from the remote. The block returned value will be passed back to the caller.

If the block raises the exception it will be reported to the caller as an error (depending on it's platofrm, will raise exception on its end or report error)

# File lib/farcall/em_farcall.rb, line 128
def on(name, &block)
  @handlers[name.to_s] = block
end
on_command(&block) click to toggle source

Process remote command. First parameter passed to the block is the method name, the rest are optional arguments of the call:

endpoint.on_command { |name, *args, **kwargs|
  if name == 'echo'
    { args: args, keyword_args: kwargs }
  else
    raise "unknown command"
  end
}

raising exceptions from the block cause farcall error to be returned back th the caller.

# File lib/farcall/em_farcall.rb, line 144
def on_command &block
  raise "unnamed handler should be present" unless block
  @unnamed_handler = block
end
on_remote_call(&block) click to toggle source

Same as on_command (compatibilty method)

# File lib/farcall/em_farcall.rb, line 150
def on_remote_call &block
  on_command &block
end
remote() click to toggle source

Get the Farcall::RemoteInterface connnected to this endpoint. Any subsequent calls with return the same instance.

# File lib/farcall/em_farcall.rb, line 156
def remote
  @remote ||= EmFarcall::Interface.new endpoint: self
end