Search code examples
rubymultithreadingruby-on-rails-4thread-safetyautotest

How do I use autotest / ActionController::TestCase with threads?


I have a thread which does a bit of processing in the background to make the controller more responsive, however, the test case fails to run. It appears to lock up printing 'EEEEEE' for about 5 minutes.

Here is my thread in the controller. exit doesn't seem to make a difference.

  Thread.new do # don't delay user response
    @post.fetchImage
    @post.save
    Thread.exit
  end

The thread has timeouts of 5s so it can't take 5-10m.

After 10m of waiting, it spits out errors:

  1) Error:
PostIntegrationTest#test_sweep_redistributes_balances_correctly:
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.002 seconds)

Solution

  • Ok I solved it by using Fibers!

      f = Fiber.new do # don't delay user response
        @post.fetchImage
        @post.save
      end
      f.resume
    

    Weird that Thread wouldn't work. Using Ruby 2.0.0.


    Ok this is even stranger than I though! Fibers would block the response to the browser in the server!

      # Threads don't work in test, and Fibers are not asynchronous in the server!
      if Rails.env == 'test'
        f = Fiber.new do # don't delay user response
          @post.fetchImage
          @post.save
        end
        f.resume
      else 
        Thread.new do # don't delay user response
          @post.fetchImage
          @post.save
        end
      end
    

    This doesn't seem right...


    Ok I found a different way, which seems more right. I'm just surprised Rails doesn't check out a DB connection automatically for a thread and check it back in when the thread is finished all in the background.

        Thread.new do # don't delay user response
          ActiveRecord::Base.connection_pool.with_connection do # checkout/checkin DB connection
            @post.fetchImage
            @post.save
          end
          # ActiveRecord::Base.connection_pool.clear_stale_cached_connections! # Paranoid mode
        end