0

When creating a PeriodicTimer in Ruby EventMachine, it's very inaccurate and seems to act randomly and incorrect. I'm wondering if there is a way to fix that or if I maybe use it in a wrong way.

Below is an example. I have a PeriodicTimer that every 10 seconds is pulling a global array (which contains mysql statements) and executes mysql commands. When running it like that, the PeriodicTimer might end up doing this only every few minutes, or it will stop doing it completely after some time, and other fancy abnormalities.

Eventmachine::run {

  EM::PeriodicTimer.new(10) {
    mysql_queue = $mysql_queue.dup
    $mysql_queue = []
    mysql_queue.each do |command|
      begin
        Mysql.query(command)
      rescue Exception => e
        puts "Error occured.. #{e} #{command}"
      end
    end
  }

  # Here follow random tasks/loops that are adding mysql statements to $mysql_queue
  100_000.times {
    if ...
      $mysql_queue << "INSERT INTO `...` (...) VALUES (...);"
    end
  }
  ...
  # ...

}

In case you are wondering, I like to use such "Mysql Queues" because it prevents race conditions. In practice, this is actually a small TCP/IP client which is handling multiple concurrent connections and executing mysql commands to log various actions.

John Meyer
  • 27
  • 1
  • 3

1 Answers1

1

What do you expect this code to do? Why do you think that timer will be ever called, if you don't pass control to EM loop? Try splitting your 100_000 loop into smaller parts:

10_000.times do
  EM.next_tick do
    10.times do
      if ...
        $mysql_queue << "INSERT INTO `...` (...) VALUES (...);"
      end
    end
  end
end

Using a global $ is a bad idea here, it's not quite clean if you're using threads that may access it or not.

phil pirozhkov
  • 4,740
  • 2
  • 33
  • 40