Class: Volt::Dispatcher
Overview
The task dispatcher is responsible for taking incoming messages from the socket channel and dispatching them to the proper handler.
Instance Method Summary collapse
-
#dispatch(channel, message) ⇒ Object
Dispatch takes an incoming Task from the client and runs it on the server, returning the result to the client.
-
#safe_method?(klass, method_name) ⇒ Boolean
Check if it is safe to use this method.
Instance Method Details
#dispatch(channel, message) ⇒ Object
Dispatch takes an incoming Task from the client and runs it on the server, returning the result to the client. Tasks returning a promise will wait to return.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/volt/tasks/dispatcher.rb', line 9 def dispatch(channel, ) callback_id, class_name, method_name, , *args = method_name = method_name.to_sym # Get the class klass = Object.send(:const_get, class_name) promise = Promise.new # Check that we are calling on a TaskHandler class and a method provide at # TaskHandler or above in the ancestor chain. if safe_method?(klass, method_name) promise.resolve(nil) # Init and send the method promise = promise.then do Thread.current['meta'] = result = klass.new(channel, self).send(method_name, *args) Thread.current['meta'] = nil result end else # Unsafe method promise.reject(RuntimeError.new("unsafe method: #{method_name}")) end if callback_id # Run the promise and pass the return value/error back to the client promise.then do |result| channel.('response', callback_id, result, nil) end.fail do |error| channel.('response', callback_id, nil, error) Volt.logger.error(error) end end end |
#safe_method?(klass, method_name) ⇒ Boolean
Check if it is safe to use this method
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/volt/tasks/dispatcher.rb', line 51 def safe_method?(klass, method_name) # Make sure the class being called is a TaskHandler. return false unless klass.ancestors.include?(TaskHandler) # Make sure the method is defined on the klass we're using and not up the hiearchy. # ^ This check prevents methods like #send, #eval, #instance_eval, #class_eval, etc... klass.ancestors.each do |ancestor_klass| if ancestor_klass.instance_methods(false).include?(method_name) return true elsif ancestor_klass == TaskHandler # We made it to TaskHandler and didn't find the method, that means it # was defined above TaskHandler, so we reject the call. return false end end return false end |