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

Instance Attribute Summary collapse

Attributes inherited from RJR::Node

#dispatcher, #message_headers, #node_id

Instance Method Summary collapse

Methods inherited from RJR::Node

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

Constructor Details

#initialize(args = {}) ⇒ Local

Nodes::Local initializer

Parameters:

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

    the options to create the local node with



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

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



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

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



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

def invoke(rpc_method, *args)
  0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
  message = RequestMessage.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)


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

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



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

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



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

def notify(rpc_method, *args)
  0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
  message = NotificationMessage.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



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

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

#to_sObject



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

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