Class: RJR::Nodes::Local

Inherits:
RJR::Node show all
Defined in:
lib/rjr/nodes/local.rb

Overview

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))

Examples:

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')

Constant Summary collapse

RJR_NODE_TYPE =
:local
PERSISTENT_NODE =
true
INDIRECT_NODE =
false

Instance Attribute Summary collapse

Attributes inherited from RJR::Node

#connection_event_handlers, #dispatcher, #message_headers, #node_id

Instance Method Summary collapse

Methods inherited from RJR::Node

#clear_event_handlers, em, #em, #halt, #indirect?, indirect?, #join, #on, persistent?, #persistent?, tp, #tp

Constructor Details

#initialize(args = {}) ⇒ Local

Nodes::Local initializer

Parameters:

  • args (Hash) (defaults to: {})

    the options to create the local node with



48
49
50
51
# File 'lib/rjr/nodes/local.rb', line 48

def initialize(args = {})
   super(args)
   @node_type = RJR_NODE_TYPE
end

Instance Attribute Details

#node_typeObject

allows clients to override the node type for the local node



44
45
46
# File 'lib/rjr/nodes/local.rb', line 44

def node_type
  @node_type
end

Instance Method Details

#invoke(rpc_method, *args) ⇒ Object

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.

Parameters:

  • rpc_method (String)

    json-rpc method to invoke on destination

  • args (Array)

    array of arguments to convert to json and invoke remote method with

Returns:

  • (Object)

    the json result retrieved from destination converted to a ruby object

Raises:

  • (Exception)

    if the destination raises an exception, it will be converted to json and re-raised here



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rjr/nodes/local.rb', line 102

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
    raise Exception, res[2]
  end
  return res[1]
end

#launch_request(req, notification) ⇒ Object

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)


82
83
84
85
86
87
# File 'lib/rjr/nodes/local.rb', line 82

def launch_request(req, notification)
  Thread.new(req,notification) { |req,notification|
    res = handle_request(req, notification, nil)
    handle_response(res.to_s) unless res.nil?
  }
end

#listenObject

Instruct Nodes to start listening for and dispatching rpc requests

Implementation of RJR::Node#listen



72
73
74
75
# File 'lib/rjr/nodes/local.rb', line 72

def listen
  # do nothing
  self
end

#notify(rpc_method, *args) ⇒ Object

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

Implementation of RJR::Node#notify

Same performance comment as invoke_request above

Parameters:

  • rpc_method (String)

    json-rpc method to invoke on destination

  • args (Array)

    array of arguments to convert to json and invoke remote method wtih



126
127
128
129
130
131
132
133
# File 'lib/rjr/nodes/local.rb', line 126

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) ⇒ Object

Send data using specified connection.

Simply dispatch local notification.

Implementation of RJR::Node#send_msg



62
63
64
65
66
67
# File 'lib/rjr/nodes/local.rb', line 62

def send_msg(msg, connection)
  # ignore response message
  unless Messages::Response.is_response_message?(msg)
    launch_request(msg, true) # .join?
  end
end

#to_sObject



53
54
55
# File 'lib/rjr/nodes/local.rb', line 53

def to_s
  "RJR::Nodes::Local<#{@node_id}>"
end