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

#initializeDispatcher

RJR::Dispatcher intializer



191
192
193
194
195
196
197
# File 'lib/rjr/dispatcher.rb', line 191

def initialize
  @handlers = Hash.new()
  @environments = Hash.new()

  @requests_lock = Mutex.new
  @requests = []
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

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.



207
208
209
210
211
212
213
214
# File 'lib/rjr/dispatcher.rb', line 207

def add_module(name)
  require name

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

  self
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



266
267
268
269
270
271
272
273
274
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
# File 'lib/rjr/dispatcher.rb', line 266

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



253
254
255
256
257
258
259
260
# File 'lib/rjr/dispatcher.rb', line 253

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



223
224
225
226
227
228
229
230
231
# File 'lib/rjr/dispatcher.rb', line 223

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



312
313
314
315
316
317
318
319
320
321
322
# File 'lib/rjr/dispatcher.rb', line 312

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



237
238
239
240
241
242
243
# File 'lib/rjr/dispatcher.rb', line 237

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



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

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