Class: Simrpc::MethodMessageController

Inherits:
Object
  • Object
show all
Defined in:
lib/simrpc/node.rb

Overview

Simrpc Method Message Controller, generates and handles method messages

Instance Method Summary collapse

Constructor Details

#initialize(schema_def) ⇒ MethodMessageController

initialize with a specified schema definition



32
33
34
# File 'lib/simrpc/node.rb', line 32

def initialize(schema_def)
  @schema_def = schema_def
end

Instance Method Details

#generate(method_name, args) ⇒ Object

Generate new new method message, setting the message target to the specified method name, and setting the fields on the message to the method arguments



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/simrpc/node.rb', line 39

def generate(method_name, args)
  mmethod = @schema_def.methods.find { |method| method.name == method_name }
  return nil if mmethod.nil?

  msg = Message::Message.new :header => {:id => IDBank.generate, :type => 'request', :target => mmethod.name }

  # if we have too few arguments, fill rest in w/ default values
  if mmethod.parameters.size > args.size
    mmethod.parameters[args.size...mmethod.parameters.size].each { |param| args << param.default }
  end

  msg.body.fields = (0...mmethod.parameters.size).collect { |i|
    Message::Field.new(:name => mmethod.parameters[i].name,
                       :value => mmethod.parameters[i].to_s(args[i], @schema_def))
  }

  return msg
end

#message_received(node, message, reply_to) ⇒ Object

should be invoked when a message is received, takes a message, converts it into a method call, and calls the corresponding handler in the provided schema. Takes return arguments and sends back to caller



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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/simrpc/node.rb', line 61

def message_received(node, message, reply_to)
  message = Message::Message::from_s(message)
  mmethod = @schema_def.methods.find { |method| method.name == message.header.target }
  return nil if mmethod.nil?

  Logger.info "received method #{mmethod.name} message "

  # For request messages, dispatch to method handler
  if message.header.type == 'request'
    return nil if mmethod.handler.nil?

    # collect the method params
    params = (0...mmethod.parameters.size).collect { |i| mmethod.parameters[i].from_s(message.body.fields[i].value, @schema_def) }

    Logger.info "invoking #{mmethod.name} handler "

    # invoke method handler
    return_values = mmethod.handler.call(*params)  # FIXME handlers can't use 'return' as this will fall through here
                                                  # FIXME throw a catch block around this call to catch all handler exceptions
    return_values = [return_values] unless return_values.is_a? Array

    # consruct and send response message using return values
    response = Message::Message.new :header => {:id => message.header.id, :type => 'response', :target => mmethod.name }
    response.body.fields = (0...mmethod.return_values.size).collect { |i|
      field_def = mmethod.return_values[i]
      Message::Field.new :name => field_def.name, :value => field_def.to_s(return_values[i], @schema_def)
      # TODO if mmethod.return_values.size > return_values.size, fill in w/ default values
    }
    Logger.info "responding to #{reply_to}"
    node.send_message(reply_to, response)
    return message.header.id, params

  # For response values just return converted return values
  else
    results = (0...mmethod.return_values.size).collect { |i|
      mmethod.return_values[i].from_s(message.body.fields[i].value, @schema_def)
    }
    return message.header.id, results

  end
end