Class: Farcall::Endpoint
- Inherits:
-
Object
- Object
- Farcall::Endpoint
- Defined in:
- lib/farcall/endpoint.rb
Overview
The protocol endpoint. Takes some transport and implements Farcall protocol over it. You can use it direcly or with Farcall::RemoteInterface and Farcall::LocalProvider helper classes.
Note that the returned data is converted to Hashie::Mash primarily for the sake of :key vs. ‘key’ ambigity that otherwise might appear depending on the transport encoding protocol. Anyway it is better than ruby hash ;)
Endpoint class is thread-safe.
Instance Attribute Summary collapse
-
#provider ⇒ Object
Set or get provider instance.
Instance Method Summary collapse
-
#abort(reason, exception = nil) ⇒ Object
:nodoc:.
-
#call(name, *args, **kwargs, &block) ⇒ Object
Call remote party.
-
#close ⇒ Object
Close endpoint and connected transport.
-
#initialize(transport) ⇒ Endpoint
constructor
Create endpoint connected to some transport.
-
#on(name, &block) ⇒ Object
Set handler to perform the named command.
-
#on_abort(&proc) ⇒ Object
The provided block will be called if endpoint functioning will be aborted.
-
#on_close(&block) ⇒ Object
Add the close handler.
-
#on_remote_call(&block) ⇒ Object
(also: #on_command)
Process remote commands.
-
#remote ⇒ Object
Get the Farcall::RemoteInterface connnected to this endpoint.
-
#sync_call(name, *args, **kwargs) ⇒ Object
Call the remote party and wait for the return.
Constructor Details
#initialize(transport) ⇒ Endpoint
Create endpoint connected to some transport
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/farcall/endpoint.rb', line 23 def initialize(transport) @transport = transport @in_serial = @out_serial = 0 @transport.on_data_received = -> (data) { begin _received(data) rescue abort :format_error, $! end } @send_lock = Mutex.new @receive_lock = Mutex.new @handlers = {} @waiting = {} 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.
19 20 21 |
# File 'lib/farcall/endpoint.rb', line 19 def provider @provider end |
Instance Method Details
#abort(reason, exception = nil) ⇒ Object
:nodoc:
52 53 54 55 56 57 58 59 |
# File 'lib/farcall/endpoint.rb', line 52 def abort reason, exception = nil puts "*** Abort: reason #{reason || exception.to_s}" @abort_hadnler and @abort_hadnler.call reason, exception if exception raise exception end close end |
#call(name, *args, **kwargs, &block) ⇒ Object
Call remote party. Retruns immediately. When remote party answers, calls the specified block if present. The block should take |error, result| parameters. If result’s content hashes or result itself are instances of th Hashie::Mash. Error could be nil or {‘class’ =>, ‘text’ => } Hashie::Mash hash. result is always nil if error is presented.
It is desirable to use Farcall::Endpoint#interface or Farcall::RemoteInterface rather than this low-level method.
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/farcall/endpoint.rb', line 77 def call(name, *args, **kwargs, &block) @send_lock.synchronize { if block != nil @waiting[@out_serial] = { time: Time.new, proc: block } _send(cmd: name.to_s, args: args, kwargs: kwargs) end } end |
#close ⇒ Object
Close endpoint and connected transport
62 63 64 65 66 |
# File 'lib/farcall/endpoint.rb', line 62 def close @transport.close @transport = nil @close_handler and @close_handler.call 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.
The provider if set is calling instead.
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)
148 149 150 |
# File 'lib/farcall/endpoint.rb', line 148 def on(name, &block) @handlers[name.to_s] = block end |
#on_abort(&proc) ⇒ Object
The provided block will be called if endpoint functioning will be aborted. The block should take |reason, exception| parameters - latter could be nil
42 43 44 |
# File 'lib/farcall/endpoint.rb', line 42 def on_abort &proc @abort_hadnler = proc end |
#on_close(&block) ⇒ Object
Add the close handler. Specified block will be called when the endpoint is been closed
47 48 49 |
# File 'lib/farcall/endpoint.rb', line 47 def on_close &block @close_handler = block end |
#on_remote_call(&block) ⇒ Object Also known as: on_command
Process remote commands. Provided block will be executed on every remote command taking parameters |name, args, kwargs|. Whatever block returns will be passed to a calling party. The same any exception that the block might raise would be send back to caller.
this block will be called onlly of there wes no ‘provider` specified and no #on handler set for the command being executed.
134 135 136 |
# File 'lib/farcall/endpoint.rb', line 134 def on_remote_call &block @on_remote_call = block end |
#remote ⇒ Object
Get the Farcall::RemoteInterface connnected to this endpoint. Any subsequent calls with return the same instance.
155 156 157 |
# File 'lib/farcall/endpoint.rb', line 155 def remote @remote ||= Farcall::Interface.new endpoint: self end |
#sync_call(name, *args, **kwargs) ⇒ Object
Call the remote party and wait for the return.
It is desirable to use Farcall::Endpoint#interface or Farcall::RemoteInterface rather than this low-level method.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/farcall/endpoint.rb', line 99 def sync_call(name, *args, **kwargs) mutex = Mutex.new resource = ConditionVariable.new error = nil result = nil calling_thread = Thread.current mutex.synchronize { same_thread = false call(name, *args, **kwargs) { |e, r| error, result = e, r # Absolutly stupid wait for self situation # When single thread is used to send and receive # - often happens in test environments if calling_thread == Thread.current same_thread = true else resource.signal end } same_thread or resource.wait(mutex) } if error raise Farcall::RemoteError.new(error['class'], error['text']) end result end |