class Metacosm::Simulation

Public Class Methods

current() click to toggle source
# File lib/metacosm/simulation.rb, line 147
def self.current
  @current ||= new
end

Public Instance Methods

apply(command) click to toggle source
# File lib/metacosm/simulation.rb, line 45
def apply(command)
  mutex.synchronize do
    received_commands.push(command)

    if command.is_a?(Hash)
      handler_module_name = command.delete(:handler_module)
      handler_class_name = command.delete(:handler_class_name)
      module_name = handler_module_name
      handler = (module_name.constantize).
        const_get(handler_class_name).new
      handler.handle(command)
    else
      handler = handler_for(command)
      handler.handle(command.attrs)
    end
  end
end
apply_event(event) click to toggle source
# File lib/metacosm/simulation.rb, line 67
def apply_event(event)
  if !@on_event_callback.nil?
    event_dto = event.attrs.merge(listener_module: event.listener_module_name, listener_class_name: event.listener_class_name)
    @on_event_callback[event_dto]
  end

  if !@event_publication_channel.nil?
    event_dto = event.attrs.merge(listener_module: event.listener_module_name, listener_class_name: event.listener_class_name)
    REDIS_PUB.with do |redis|
      redis.publish(@event_publication_channel, Marshal.dump(event_dto))
    end
  end

  if !local_events_disabled?
    listener = listener_for(event)
    if event.attrs.any?
      listener.receive(event.attrs)
    else
      listener.receive
    end
  end
end
clear!() click to toggle source
# File lib/metacosm/simulation.rb, line 151
def clear!
  @events = []
  @command_queue && @command_queue.clear
end
command_queue() click to toggle source
# File lib/metacosm/simulation.rb, line 16
def command_queue
  @command_queue ||= Queue.new
end
conduct!() click to toggle source
# File lib/metacosm/simulation.rb, line 24
def conduct!
  @conductor_thread = Thread.new { execute }
end
disable_local_events() click to toggle source
# File lib/metacosm/simulation.rb, line 130
def disable_local_events
  @local_events_disabled = true
end
event_queue() click to toggle source
# File lib/metacosm/simulation.rb, line 20
def event_queue
  @event_queue ||= Queue.new
end
events() click to toggle source
# File lib/metacosm/simulation.rb, line 143
def events
  @events ||= []
end
execute() click to toggle source
# File lib/metacosm/simulation.rb, line 28
def execute
  while true
    if (command=command_queue.pop)
      apply(command)
    end
    Thread.pass
  end
end
fire(command) click to toggle source
# File lib/metacosm/simulation.rb, line 12
def fire(command)
  command_queue.push(command)
end
halt!() click to toggle source
# File lib/metacosm/simulation.rb, line 37
def halt!
  @conductor_thread.terminate
end
local_events_disabled?() click to toggle source
# File lib/metacosm/simulation.rb, line 134
def local_events_disabled?
  @local_events_disabled ||= false
end
mutex() click to toggle source
# File lib/metacosm/simulation.rb, line 41
def mutex
  @mutex = Mutex.new
end
on_event(publish_to:nil,&blk) click to toggle source
# File lib/metacosm/simulation.rb, line 90
def on_event(publish_to:nil,&blk)
  unless publish_to.nil?
    @event_publication_channel = publish_to
  end

  if block_given?
    @on_event_callback = blk
  end
end
params() click to toggle source

TODO protected? def redis_connection

Redis.new

end

# File lib/metacosm/simulation.rb, line 8
def params
  @params ||= {}
end
receive(event, record: true) click to toggle source
# File lib/metacosm/simulation.rb, line 138
def receive(event, record: true)
  events.push(event) if record
  apply_event(event)
end
received_commands() click to toggle source
# File lib/metacosm/simulation.rb, line 63
def received_commands
  @commands_received ||= []
end
subscribe_for_commands(channel:) click to toggle source
# File lib/metacosm/simulation.rb, line 100
def subscribe_for_commands(channel:)
  p [ :subscribe_to_command_channel, channel: channel ]
  @command_subscription_thread = Thread.new do
    REDIS_SUB.with do |redis|
      begin
        redis.subscribe(channel) do |on|
          on.subscribe do |chan, subscriptions|
            puts "Subscribed to ##{chan} (#{subscriptions} subscriptions)"
          end

          on.message do |chan, message|
            # puts "##{chan}: #{message}"
            command_data = Marshal.load(message)
            p [ :got_message, command_data: command_data ]
            apply(command_data)
          end

          on.unsubscribe do |chan, subscriptions|
            puts "Unsubscribed from ##{chan} (#{subscriptions} subscriptions)"
          end
        end
      rescue Redis::BaseConnectionError => error
        puts "#{error}, retrying in 1s"
        sleep 1
        retry
      end
    end
  end
end

Protected Instance Methods

construct_handler_for(command) click to toggle source
# File lib/metacosm/simulation.rb, line 162
def construct_handler_for(command)
  module_name = command.handler_module_name
  (module_name.constantize).
    const_get(command.handler_class_name).new
rescue => ex
  binding.pry
  raise ex
end
construct_listener_for(event) click to toggle source
# File lib/metacosm/simulation.rb, line 176
def construct_listener_for(event)
  module_name = event.listener_module_name
  listener = (module_name.constantize).const_get(event.listener_class_name).new(self)
  listener
end
handler_for(command) click to toggle source
# File lib/metacosm/simulation.rb, line 157
def handler_for(command)
  @handlers ||= {}
  @handlers[command.self_class_name] ||= construct_handler_for(command)
end
listener_for(event) click to toggle source
# File lib/metacosm/simulation.rb, line 171
def listener_for(event)
  @listeners ||= {}
  @listeners[event.self_class_name] ||= construct_listener_for(event)
end