Class: RJR::Dispatcher

Inherits:
Object show all
Defined in:
lib/rjr/dispatcher.rb

Overview

Primary RJR JSON-RPC method dispatcher.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Dispatcher

RJR::Dispatcher intializer



194
195
196
197
198
199
# File 'lib/rjr/dispatcher.rb', line 194

def initialize(args = {})
  @keep_requests = args[:keep_requests] || false

  clear!
  @requests_lock = Mutex.new
end

Instance Attribute Details

#environmentsObject (readonly)

Registered json-rpc request signatures and environments which to execute handlers in



185
186
187
# File 'lib/rjr/dispatcher.rb', line 185

def environments
  @environments
end

#handlersObject (readonly)

Registered json-rpc request signatures and corresponding handlers



182
183
184
# File 'lib/rjr/dispatcher.rb', line 182

def handlers
  @handlers
end

#keep_requestsObject

Flag toggling whether or not to keep requests (& responses) around.



188
189
190
# File 'lib/rjr/dispatcher.rb', line 188

def keep_requests
  @keep_requests
end

Instance Method Details

#add_module(name) ⇒ Object Also known as: add_modules

Loads module from fs and adds handlers defined there

Assumes module includes a ‘dispatch_<module_name>’ method which accepts a dispatcher and defines handlers on it.

Parameters:

  • name (String)

    location which to load module(s) from, may be a file, directory, or path specification (dirs seperated with ‘:’)

Returns:

  • self



216
217
218
219
220
221
222
223
# File 'lib/rjr/dispatcher.rb', line 216

def add_module(name)
  require name

  m = name.downcase.gsub(File::SEPARATOR, '_')
  method("dispatch_#{m}".intern).call(self)

  self
end

#clear!Object

Return dispatcher to its initial state



202
203
204
205
206
# File 'lib/rjr/dispatcher.rb', line 202

def clear!
  @handlers      = {}
  @environments  = {}
  @requests      = []
end

#dispatch(args = {}) ⇒ Object

Dispatch received request. (used internally by nodes).

Arguments should include :rjr_method and other parameters required to construct a valid Request instance



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/rjr/dispatcher.rb', line 275

def dispatch(args = {})
   # currently we match method name string or regex against signature
   # TODO not using concurrent access protection, assumes all handlers are registered
   #      before first dispatch occurs
   handler = @handlers.find { |k,v|
     k.is_a?(String)         ?
     k == args[:rjr_method] :
     k =~ args[:rjr_method] }

   # TODO currently just using last environment that matches,
   #      allow multiple environments to be used?
   environment = @environments.keys.select { |k|
     k.is_a?(String)         ?
     k == args[:rjr_method] :
     k =~ args[:rjr_method]
   }.last

   return Result.method_not_found(args[:rjr_method]) if handler.nil?

   # TODO compare arity of handler to number of method_args passed in
   request = Request.new args.merge(:rjr_handler  => handler.last)

   # set request environment
   request.extend(@environments[environment]) unless environment.nil?

   begin
     retval  = request.handle
     request.result  = Result.new(:result => retval)

   rescue Exception => e
     RJR::Logger.warn ["Exception Raised in #{args[:rjr_method]} handler #{e}"] +
                       e.backtrace
     request.result =
       Result.new(:error_code => -32000,
                  :error_msg  => e.to_s,
                  :error_class => e.class)

   end

   @requests_lock.synchronize { @requests << request } if @keep_requests
   return request.result
end

#env(signature, environment) ⇒ Object

Register environment to run json-rpc handler w/ dispatcher.

Currently environments may be set to modules which requests will extend before executing handler

Parameters:

  • signature (String, Regex)

    request signature to match

  • module (Module)

    which to extend requests with

Returns:

  • self



262
263
264
265
266
267
268
269
# File 'lib/rjr/dispatcher.rb', line 262

def env(signature, environment)
  if signature.is_a?(Array)
    signature.each { |s| env(s, environment) }
    return self
  end
  @environments[signature] = environment
  self
end

#handle(signature, callback = nil, &bl) ⇒ Object

Register json-rpc handler with dispatcher

Parameters:

  • signature (String, Regex)

    request signature to match

  • callable (Callable)

    callable object which to bind to signature

  • &bl (Callable)

    block parameter will be set to callback if specified

Returns:

  • self



232
233
234
235
236
237
238
239
240
# File 'lib/rjr/dispatcher.rb', line 232

def handle(signature, callback = nil, &bl)
  if signature.is_a?(Array)
    signature.each { |s| handle(s, callback, &bl) }
    return self
  end
  @handlers[signature] = callback unless callback.nil?
  @handlers[signature] = bl       unless bl.nil?
  self
end

#handle_response(result) ⇒ Object

Handle responses received from rjr requests. (used internally by nodes)

Returns return-value of method handler or raises error



321
322
323
324
325
326
327
328
329
330
331
# File 'lib/rjr/dispatcher.rb', line 321

def handle_response(result)
   unless result.success
     #if result.error_class
     #  TODO needs to be constantized first (see TODO in lib/rjr/message)
     #  raise result.error_class.new(result.error_msg) unless result.success
     #else
       raise Exception, result.error_msg
     #end
   end
   return result.result
end

#handles?(rjr_method) ⇒ true, false

Return boolean indicating if dispatcher can handle method

Parameters:

  • string (String)

    rjr method to match

Returns:

  • (true, false)

    indicating if requests to specified method will be matched



246
247
248
249
250
251
252
# File 'lib/rjr/dispatcher.rb', line 246

def handles?(rjr_method)
   !@handlers.find { |k,v|
     k.is_a?(String)         ?
     k == rjr_method :
     k =~ rjr_method
   }.nil?
end

#requestsObject

Requests which have been dispatched



191
# File 'lib/rjr/dispatcher.rb', line 191

def requests ; @requests_lock.synchronize { Array.new(@requests) } ; end