Class: Nobject::Local
- Inherits:
-
Object
- Object
- Nobject::Local
- Defined in:
- lib/nobject/local.rb
Overview
this class is used by the client application, wraps a local object, pushes it to a Nobject::Serve4r, which will then send method calls to a matching Nobject::Remote object
Defined Under Namespace
Classes: InvalidMethod, MethodInvocationRetriesExceeded, MethodRequestFailure, MethodResponseFailure, UnknownReturnDataType
Constant Summary collapse
- MAX_RETRIES =
3
Instance Method Summary collapse
-
#!~(other) ⇒ Object
method overridden from Object class.
- #<=>(other) ⇒ Object
- #===(other) ⇒ Object
-
#initialize(host, port, obj) ⇒ Local
constructor
host: the hostname of the server to push obj to port: the port number of the server to push obj to obj: the obj to store over the network.
- #inspect ⇒ Object
- #is_a?(klass) ⇒ Boolean
- #method_missing(method, *args, **kwargs, &block) ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(host, port, obj) ⇒ Local
host: the hostname of the server to push obj to port: the port number of the server to push obj to obj: the obj to store over the network
ex:
# this will create a new Nobject::Local, then push it to the specified
server Nobject::Local.new('localhost', 1234, <object>)
17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nobject/local.rb', line 17 def initialize(host, port, obj) @msg_counter = 0 @socket = TCPSocket.new(host, port) @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) obj_bytes = Marshal.dump(obj) File.open('/tmp/nobject.log', 'a') {|f| f.puts "L:##{@msg_counter += 1} sz#{obj_bytes.length}"; f.flush } @socket.send([obj_bytes.length].pack('Q>'), 0) @socket.send(obj_bytes, 0) @socket.flush end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, **kwargs, &block) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/nobject/local.rb', line 30 def method_missing(method, *args, **kwargs, &block) msg = { method: method, args: args } msg_bytes = Marshal.dump(msg) retries = 0 loop do raise MethodInvocationRetriesExceeded.new("Exceeded retry limit (#{MAX_RETRIES})") if retries == MAX_RETRIES begin @socket.send([msg_bytes.length].pack('Q>'), 0) File.open('/tmp/nobject.log', 'a') {|f| f.puts " LMS:##{@msg_counter += 1} sz#{msg_bytes.length} m:#{method}"; f.flush } @socket.send(msg_bytes, 0) @socket.flush rescue Exception raise Local::MethodRequestFailure.new("did not receive response from call to `#{method}' over the network") end return_data = begin msg_size = @socket.recv(8).unpack('Q>').first raw_bytes = @socket.recv(msg_size) File.open('/tmp/nobject.log', 'a') {|f| f.puts " LMGotit :##{@msg_counter += 1} sz#{msg_size} bytes:#{raw_bytes.length} m:#{method}"; f.flush } if msg_size != raw_bytes.length retries += 1 print "\a" # TODO: consider removing this after the # retry logic seems solid, it's extra, # literal noise :) redo end Marshal.load(raw_bytes) rescue Exception => e # TODO: consider removing this rescue block: # this rescue may be unreachable now, since the only # time it used to happen was when: # msg_size != raw_bytes.length # # ... which is now handled by the retry logic above error_msg = " did not receive response from call to `\#{method}' over the network\n would have been msg_id \#{@msg_counter} OR \#{@msg_counter + 1} when trying to receive \#{msg_size} bytes\n caused by \#{e.class.name}\n exception backtrace:\n \#{e.backtrace.join(\"\\n \")}\n MSG\n raise Local::MethodResponseFailure.new(error_msg)\n end\n\n break (\n case return_data.first\n when :ok then return_data.last\n when :raise then raise return_data.last\n else\n raise Local::UnknownReturnDataType.new(\"unknown data type '\#{return_data.first}' within Nobject::Local (Nobject::Local::UnknownReturnDataType)\")\n end\n )\n end\nend\n" |
Instance Method Details
#!~(other) ⇒ Object
method overridden from Object class
91 |
# File 'lib/nobject/local.rb', line 91 def !~(other); method_missing(:is_a?, other); end |
#<=>(other) ⇒ Object
92 |
# File 'lib/nobject/local.rb', line 92 def <=>(other); method_missing(:<=>, other); end |
#===(other) ⇒ Object
93 |
# File 'lib/nobject/local.rb', line 93 def ===(other); method_missing(:<=>, other); end |
#inspect ⇒ Object
95 |
# File 'lib/nobject/local.rb', line 95 def inspect; method_missing(:inspect); end |
#is_a?(klass) ⇒ Boolean
94 |
# File 'lib/nobject/local.rb', line 94 def is_a?(klass); method_missing(:is_a?, klass); end |
#to_s ⇒ Object
96 |
# File 'lib/nobject/local.rb', line 96 def to_s; method_missing(:to_s); end |