lib/plezi/handlers/controller_magic.rb in plezi-0.7.2 vs lib/plezi/handlers/controller_magic.rb in plezi-0.7.3

- old
+ new

@@ -191,11 +191,11 @@ # respond to save 'new' special case return :save if request.request_method.match(/POST|PUT/) && params[:id].nil? || params[:id] == 'new' # set DELETE method if simulated request.request_method = 'DELETE' if params[:_method].to_s.downcase == 'delete' # respond to special :id routing - return params[:id].to_sym if params[:id] && available_public_methods.include?(params[:id].to_sym) + return params[:id].to_sym if params[:id] && self.class.available_public_methods.include?(params[:id].to_sym) #review general cases case request.request_method when 'GET', 'HEAD' return :index unless params[:id] return :show @@ -205,22 +205,10 @@ return :delete end false end - # lists the available methods that will be exposed to HTTP requests - def available_public_methods - # set class global to improve performance while checking for supported methods - @@___available_public_methods___ ||= available_routing_methods - [:before, :after, :save, :show, :update, :delete, :initialize, :on_message, :pre_connect, :on_connect, :on_disconnect] - end - - # lists the available methods that will be exposed to the HTTP router - def available_routing_methods - # set class global to improve performance while checking for supported methods - @@___available_routing_methods___ ||= (((self.class.public_instance_methods - Object.public_instance_methods) - Plezi::ControllerMagic::InstanceMethods.instance_methods).delete_if {|m| m.to_s[0] == '_'}) - end - ## WebSockets Magic # WebSockets. # # Use this to brodcast an event to all 'sibling' websockets (websockets that have been created using the same Controller class). @@ -259,11 +247,10 @@ # &block:: an optional block to be used as a callback. # # the method will be called asynchrnously for each sibling instance of this Controller class. def collect method_name, *args, &block return Plezi.callback(self, :collect, *args, &block) if block - r = [] ObjectSpace.each_object(self.class) { |controller| r << controller.method(method_name).call(*args) if controller.accepts_broadcast? && (controller.object_id != self.object_id) } return r end @@ -278,39 +265,93 @@ end module ClassMethods public + # lists the available methods that will be exposed to HTTP requests + def available_public_methods + # set class global to improve performance while checking for supported methods + Plezi.cached?(self.superclass.name + "_p&rt") ? Plezi.get_cached(self.superclass.name + "_p&rt") : Plezi.cache_data(self.superclass.name + "_p&rt", available_routing_methods - [:before, :after, :save, :show, :update, :delete, :initialize, :on_message, :pre_connect, :on_connect, :on_disconnect]) + end + + # lists the available methods that will be exposed to the HTTP router + def available_routing_methods + # set class global to improve performance while checking for supported methods + Plezi.cached?(self.superclass.name + "_r&rt") ? Plezi.get_cached(self.superclass.name + "_r&rt") : Plezi.cache_data(self.superclass.name + "_r&rt", (((public_instance_methods - Object.public_instance_methods) - Plezi::ControllerMagic::InstanceMethods.instance_methods).delete_if {|m| m.to_s[0] == '_'}) ) + end + + # resets this controller's router, to allow for dynamic changes + def reset_routing_cache + Plezi.clear_cached(self.superclass.name + "_p&rt") + Plezi.clear_cached(self.superclass.name + "_r&rt") + available_routing_methods + available_public_methods + end + + # a callback that resets the class router whenever a method (a potential route) is added + def method_added(id) + reset_routing_cache + end + # a callback that resets the class router whenever a method (a potential route) is removed + def method_removed(id) + reset_routing_cache + end + # a callback that resets the class router whenever a method (a potential route) is undefined (using #undef_method). + def method_undefined(id) + reset_routing_cache + end + # reviews the Redis connection, sets it up if it's missing and returns the Redis connection. # # todo: review thread status? (incase an exception killed it) def redis_connection + # return false unless defined?(Redis) && ENV['PL_REDIS_URL'] + # return @@redis if defined?(@@redis_sub_thread) && @@redis + # @@redis_uri ||= URI.parse(ENV['PL_REDIS_URL']) + # @@redis ||= Redis.new(host: @@redis_uri.host, port: @@redis_uri.port, password: @@redis_uri.password) + # @@redis_sub_thread = Thread.new do + # begin + # Redis.new(host: @@redis_uri.host, port: @@redis_uri.port, password: @@redis_uri.password).subscribe(redis_channel_name) do |on| + # on.message do |channel, msg| + # args = JSON.parse(msg) + # params = args.shift + # __inner_process_broadcast params['_pl_ignore_object'], params['_pl_method_broadcasted'].to_sym, args + # end + # end + # rescue Exception => e + # Plezi.error e + # retry + # end + # end + # raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @@redis + # @@redis return false unless defined?(Redis) && ENV['PL_REDIS_URL'] - return @@redis if defined?(@@redis_sub_thread) && @@redis + return Plezi.get_cached(self.superclass.name + "_b") if Plezi.cached?(self.superclass.name + "_b") @@redis_uri ||= URI.parse(ENV['PL_REDIS_URL']) - @@redis ||= Redis.new(host: @@redis_uri.host, port: @@redis_uri.port, password: @@redis_uri.password) - @@redis_sub_thread = Thread.new do + Plezi.cache_data self.superclass.name + "_b", Redis.new(host: @@redis_uri.host, port: @@redis_uri.port, password: @@redis_uri.password) + raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless Plezi.cached?(self.superclass.name + "_b") + t = Thread.new do begin Redis.new(host: @@redis_uri.host, port: @@redis_uri.port, password: @@redis_uri.password).subscribe(redis_channel_name) do |on| on.message do |channel, msg| args = JSON.parse(msg) params = args.shift - __inner_process_broadcast params['_an_ignore_object'], params['_an_method_broadcasted'].to_sym, args + __inner_process_broadcast params['_pl_ignore_object'], params['_pl_method_broadcasted'].to_sym, args end end rescue Exception => e Plezi.error e retry end end - raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @@redis - @@redis + Plezi.cache_data self.superclass.name + "_t", t + Plezi.get_cached(self.superclass.name + "_b") end # returns a Redis channel name for this controller. def redis_channel_name - self.name.to_s + self.superclass.name.to_s end # broadcasts messages (methods) for this process def __inner_process_broadcast ignore, method_name, args, &block ObjectSpace.each_object(self) { |controller| Plezi.callback controller, method_name, *args, &block if controller.accepts_broadcast? && (!ignore || controller.uuid != ignore) } @@ -319,10 +360,10 @@ # broadcasts messages (methods) between all processes (using Redis). def __inner_redis_broadcast ignore, method_name, args, &block return false unless redis_connection raise "Radis broadcasts cannot accept blocks (no inter-process callbacks of memory sharing)!" if block # raise "Radis broadcasts accept only one paramater, which is an optional Hash (no inter-process memory sharing)" if args.length > 1 || (args[0] && !args[0].is_a?(Hash)) - args.unshift ({_an_method_broadcasted: method_name, _an_ignore_object: ignore}) + args.unshift ({_pl_method_broadcasted: method_name, _pl_ignore_object: ignore}) redis_connection.publish(redis_channel_name, args.to_json ) true end # WebSockets.