Module: Anorexic::ControllerMagic::ClassMethods

Defined in:
lib/anorexic/handlers/controller_magic.rb

Instance Method Summary collapse

Instance Method Details

#__inner_process_broadcast(ignore, method_name, args, &block) ⇒ Object

broadcasts messages (methods) for this process


309
310
311
# File 'lib/anorexic/handlers/controller_magic.rb', line 309

def __inner_process_broadcast ignore, method_name, args, &block
	ObjectSpace.each_object(self) { |controller| Anorexic.callback controller, method_name, *args, &block if controller.accepts_broadcast? && (!ignore || controller.uuid != ignore) }
end

#__inner_redis_broadcast(ignore, method_name, args, &block) ⇒ Object

broadcasts messages (methods) between all processes (using Redis).


314
315
316
317
318
319
320
321
# File 'lib/anorexic/handlers/controller_magic.rb', line 314

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})
	redis_connection.publish(redis_channel_name, args.to_json )
	true
end

#broadcast(method_name, *args, &block) ⇒ Object

WebSockets.

Class method.

Use this to brodcast an event to all connections.

accepts:

method_name

a Symbol with the method's name that should respond to the broadcast.

*args

any arguments that should be passed to the method (IF REDIS IS USED, LIMITATIONS APPLY).

this method accepts and optional block (NON-REDIS ONLY) to be used as a callback for each sibling's event.

the method will be called asynchrnously for each sibling instance of this Controller class.


336
337
338
339
# File 'lib/anorexic/handlers/controller_magic.rb', line 336

def broadcast method_name, *args, &block
	return false unless public_instance_methods.include?(method_name)
	__inner_redis_broadcast(nil, method_name, args, &block) || __inner_process_broadcast(nil, method_name.to_sym, args, &block)
end

#collect(method_name, *args, &block) ⇒ Object

WebSockets.

Class method.

Use this to collect data from all websockets for the calling class (websockets that have been created using the same Controller class).

This method will call the requested method on all instance and return an Array of the returned values (including nil values).

This method will block the excecution unless a block is passed to the method - in which case

the block will used as a callback and recieve the Array as a parameter.

i.e.

this will block: `collect :_get_id`

this will not block: `collect(:_get_id) {|a| puts “got #{a.length} responses.”; a.each { |id| puts “#id”} }

accepts:

method_name

a Symbol with the method's name that should respond to the broadcast.

*args

any arguments that should be passed to the method.

&block

an optional block to be used as a callback.

the method will be called asynchrnously for each instance of this Controller class.


364
365
366
367
368
369
370
# File 'lib/anorexic/handlers/controller_magic.rb', line 364

def collect method_name, *args, &block				
	return Anorexic.push_event(self.method(:collect), *args, &block) if block

	r = []
	ObjectSpace.each_object(self) { |controller|  r << controller.method(method_name).call(*args) if controller.accepts_broadcast? }
	return r
end

#redis_channel_nameObject

returns a Redis channel name for this controller.


304
305
306
# File 'lib/anorexic/handlers/controller_magic.rb', line 304

def redis_channel_name
	self.name.to_s
end

#redis_connectionObject

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)


280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/anorexic/handlers/controller_magic.rb', line 280

def redis_connection
	return false unless defined?(Redis) && ENV['AN_REDIS_URL']
	return @@redis if defined?(@@redis_sub_thread) && @@redis
	@@redis_uri ||= URI.parse(ENV['AN_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['_an_ignore_object'], params['_an_method_broadcasted'].to_sym, args
				end
			end						
		rescue Exception => e
			Anorexic.error e
			retry
		end
	end
	raise "Redis connction failed for: #{ENV['AN_REDIS_URL']}" unless @@redis
	@@redis
end