Class: EmFarcall::Endpoint
- Inherits:
-
Object
- Object
- EmFarcall::Endpoint
- Defined in:
- lib/farcall/em_farcall.rb
Overview
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.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#provider ⇒ Object
Set or get provider instance.
Instance Method Summary collapse
-
#call(name, *args, **kwargs, &block) ⇒ Promise
Call the remote method with specified name and arguments calling block when done.
-
#close ⇒ Object
Close the endpoint.
-
#error(text) ⇒ Object
Report error via errback and the endpoint.
-
#initialize(input_channel, output_channel, errback = nil, provider: nil) ⇒ Endpoint
constructor
Create new endpoint to work with input and output channels.
-
#on(name, &block) ⇒ Object
Set handler to perform the named command.
-
#on_command(&block) ⇒ Object
Process remote command.
-
#on_remote_call(&block) ⇒ Object
Same as #on_command (compatibilty method).
-
#remote ⇒ Object
Get the Farcall::RemoteInterface connnected to this endpoint.
Constructor Details
#initialize(input_channel, output_channel, errback = nil, provider: nil) ⇒ Endpoint
Create new endpoint to work with input and output channels
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# 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 |
Instance Attribute Details
#provider ⇒ Object
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.
63 64 65 |
# File 'lib/farcall/em_farcall.rb', line 63 def provider @provider end |
Instance Method Details
#call(name, *args, **kwargs, &block) ⇒ Promise
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}"
}
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# 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 ⇒ Object
Close the endpoint
109 110 111 |
# File 'lib/farcall/em_farcall.rb', line 109 def close super end |
#error(text) ⇒ Object
Report error via errback and the endpoint
114 115 116 117 118 119 120 |
# 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) ⇒ Object
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)
128 129 130 |
# File 'lib/farcall/em_farcall.rb', line 128 def on(name, &block) @handlers[name.to_s] = block end |
#on_command(&block) ⇒ Object
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.
144 145 146 147 |
# 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) ⇒ Object
Same as #on_command (compatibilty method)
150 151 152 |
# File 'lib/farcall/em_farcall.rb', line 150 def on_remote_call &block on_command &block end |