Search code examples
mysqlruby-on-railsrubyactiverecordtimeout

Active Record mySQL Timeout ERROR -- : worker=0 PID:(xxxxx) timeout (61s > 60s), killing


I have a async action on my controller that can perform a heavy SQL query depending on user input.

  @results = ActiveRecord::Base
  .connection
  .select_all(query_string)
  .map do |record|
    Hashie::Mash.new(record)
  end

When it happens, the only response I get from the server is

E, [2020-02-05T16:14:04.133233 #59909] ERROR -- : worker=0 PID:60952 timeout (61s > 60s), killing
E, [2020-02-05T16:14:04.159372 #59909] ERROR -- : reaped #<Process::Status: pid 60952 SIGKILL (signal 9)> worker=0

Is there any way I can capture this timeout on the backend, to give the user the correct feedback?

Tried using Timeout::timeout(x) but with no success.


Solution

  • You could add another, shorter timeout yourself and handle the situation before the worker gets killed. Something like this might be a good start:

    require 'timeout'
    
    begin
      # 5 seconds before the MySQL timeout would kick in
      Timeout.timeout(55) do
        # have only the slow query in this block
        @database_results = ActiveRecord::Base.connection.select_all(query_string)
      end
    rescue Timeout::Error
      # Handle the timeout. Proper error handling depends on your application.
      # In a controller you might just want to return an error page, in a 
      # background worker you might want to record the error in your database.
    end
    
    # time to translate the data should not count towards the timeout
    @results = @database_results.map  { |r| Hashie::Mash.new(r) }