Following this blog post, http://blog.arkency.com/2015/09/testing-race-conditions/
I am trying to test concurrency. But in my specs, I am not able to find the record when I spin up a new thread or fork a process.
describe 'test concurrency' do
let(:order_1) { create(:order) }
let(:order_2) { create(:order) }
let(:order_3) { create(:order) }
let(:order_4) { create(:order) }
let(:product) { create(:product) }
it 'test concurrency' do
wait_for_all_threads = true
product.update(quantity_available: 4, quantity_sold: 0, quantity_in_carts: 0)
orders = [order_1, order_2, order_3, order_4]
# Objects are persisted in here
# because order_n.persisted => true
# product.persisted => true
# product.reload works without issue (and this is essentially what causes the RecordNotFound error in Order#add_item)
threads = orders.map do |order|
Thread.new do
# Objects cannot be found in the database
true while wait_for_all_threads
item = order.add_item(product, 1)
order_items << item
end
end
wait_for_all_threads = false
threads.each(&:join)
# ...
# here comes all the expects ...
# not gonna post it because it's not what matters in this question
end
end
After research, I've set these:
DatabaseCleaner.strategy = :truncation
config.use_transactional_fixtures = false
But no luck.
So the issue is, within the new thread, none of the created objects can be found in the database.
Some clues as I am digging:
- The database is empty the entire time when I connect directly via a sql client. (When I add a break point in the test, and verify the object is
persisted?
) - Does factory girl / rspec actually commit the data to the database? If not, then a new thread would not be able to read it because it's still in the bin log or memory? (This prompts to me because I remember
after_commit
won't run in rspec)