class RJR::Nodes::Local

Local node definition, implements the {RJR::Node} interface to listen for and invoke json-rpc requests via local handlers

This is useful for situations in which you would like to invoke registered json-rpc handlers locally, enforcing the same constraints as you would on a json-rpc request coming in remotely.

Note this only dispatches to the methods defined on the local dispatcher!

If you have two local nodes, they will have seperate dispatchers unless you assign them the same object (eg node2.dispatcher = node1.dispatcher or node2 = new RJR::Nodes::Local.new(:dispatcher :=> node1.dispatcher))

@example Listening for and dispatching json-rpc requests locally

# initialize node
node = RJR::Nodes::Local.new :node_id => 'node'

node.dispatcher.handle('hello') do |name|
  @rjr_node_type == :local ? "Hello superuser #{name}" : "Hello #{name}!"
end

# invoke request
node.invoke('hello', 'mo')

Constants

INDIRECT_NODE
PERSISTENT_NODE
RJR_NODE_TYPE

Attributes

node_type[RW]

allows clients to override the node type for the local node

Public Class Methods

new(args = {}) click to toggle source

Nodes::Local initializer @param [Hash] args the options to create the local node with

Calls superclass method RJR::Node::new
# File lib/rjr/nodes/local.rb, line 48
def initialize(args = {})
   super(args)
   @node_type = RJR_NODE_TYPE
end

Public Instance Methods

invoke(rpc_method, *args) click to toggle source

Instructs node to send rpc request, and wait for and return response

Implementation of RJR::Node#invoke

If strictly confirming to other nodes, this would use event machine to launch a thread pool job to dispatch request and block on result. Optimized for performance reasons but recognize that the semantics of using the local node will be somewhat different.

@param [String] rpc_method json-rpc method to invoke on destination @param [Array] args array of arguments to convert to json and invoke remote method with @return [Object] the json result retrieved from destination converted to a ruby object @raise [Exception] if the destination raises an exception, it will be converted to json and re-raised here

# File lib/rjr/nodes/local.rb, line 109
def invoke(rpc_method, *args)
  0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
  message = Messages::Request.new(:method => rpc_method,
                                  :args   => args,
                                  :headers => @message_headers)
  launch_request(message.to_s, false)

  # TODO optional timeout for response ?
  res = wait_for_result(message)

  if res.size > 2
    fail res[2]
  end
  return res[1]
end
launch_request(req, notification) click to toggle source

Helper to launch request in new thread

This needs to happen so that each request runs in its own context (or close to it, globals will still be available, but locks will

not be locally held, etc)
# File lib/rjr/nodes/local.rb, line 83
def launch_request(req, notification)
  Thread.new(req, notification) { |req, notification|
    inter = req.is_a?(Messages::Intermediate) ?    req :
                      Messages::Intermediate.parse(req)
    res = handle_request(inter, notification, nil)

    unless res.nil?
      inter = Messages::Intermediate.parse(res.to_s)
      handle_response(inter)
    end
  }
end
listen() click to toggle source

Instruct Nodes to start listening for and dispatching rpc requests

Implementation of RJR::Node#listen

# File lib/rjr/nodes/local.rb, line 73
def listen
  # do nothing
  self
end
notify(rpc_method, *args) click to toggle source

Instructs node to send rpc notification (immediately returns / no response is generated)

Implementation of RJR::Node#notify

Same performance comment as invoke_request above

@param [String] rpc_method json-rpc method to invoke on destination @param [Array] args array of arguments to convert to json and invoke remote method wtih

# File lib/rjr/nodes/local.rb, line 133
def notify(rpc_method, *args)
  0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
  message = Messages::Notification.new(:method => rpc_method,
                                       :args   => args,
                                       :headers => @message_headers)
  launch_request(message.to_s, true) #.join ?
  nil
end
send_msg(msg, connection) click to toggle source

Send data using specified connection.

Simply dispatch local notification.

Implementation of RJR::Node#send_msg

# File lib/rjr/nodes/local.rb, line 62
def send_msg(msg, connection)
  # ignore response message
  inter = Messages::Intermediate.parse(msg)
  unless Messages::Response.is_response_message?(inter)
    launch_request(inter, true) # .join?
  end
end
to_s() click to toggle source
# File lib/rjr/nodes/local.rb, line 53
def to_s
  "RJR::Nodes::Local<#{@node_id}>"
end