Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreaded ActiveRecord requests in rspec

I'm trying to recreate a race condition in a test, so I can try out some solutions. I find that in the threads I create in my test, ActiveRecord always returns 0 for counts and nil for finds. For example, with 3 rows in the table "foos":

  it "whatever" do
    puts Foo.count
    5.times do
      Thread.new do
        puts Foo.count
      end
    end
  end

will print

3
0
0
0
0
0

test.log shows the expected query, the expected 6 times:

 SELECT count(*) AS count_all FROM `active_agents`

Any idea what's going on here?

like image 334
jeem Avatar asked May 15 '10 18:05

jeem


People also ask

Is Ruby on Rails multi threaded?

Dissecting Ruby on Rails 5 - Become a Professional Developer Often on a single CPU machine, multiple threads are not actually executed in parallel, but parallelism is simulated by interleaving the execution of the threads. Ruby makes it easy to write multi-threaded programs with the Thread class.

Is Ruby multithreaded or single threaded?

The Ruby Interpreter is single threaded, which is to say that several of its methods are not thread safe. In the Rails world, this single-thread has mostly been pushed to the server.

Can Ruby use multiple cores?

A single thread executes on one CPU core, so if you write a ruby program, then it is executed only one core of CPU and if you have quad-core CPU then other 3 cores are not utilize to execute your ruby program. Threading makes ruby program to utilize more memory and CPU to execute faster and achieve concurrency.

What does thread join do in Ruby?

Calling Thread. join blocks the current (main) thread. However not calling join results in all spawned threads to be killed when the main thread exits.


1 Answers

I'm assuming ActiveRecord opens a dedicated database connection for each thread. Since each RSpec example is wrapped inside a transaction, the other threads might not see the changes.

Try disabling transactional fixtures for that spec.

describe "thread test" do
  self.use_transactional_fixtures = false

  it "whatever" do
    puts Foo.count
    5.times do
      Thread.new do
        puts Foo.count
      end
    end
  end
end
like image 70
triskweline Avatar answered Sep 20 '22 18:09

triskweline