I'm trying to set up a test around concurrency. The end goal is to test that a service using ActiveRecord skips locked
records in PostgreSQL.
This works great in two consoles:
# in console 1
queue = MyFancyQueue.first
item_1 = queue.items.first
item_1.with_lock { sleep 30 } # locks item_1 for 30 seconds
# in console 2, while item_1 is locked
queue = MyFancyQueue.first
queue.items.first # => item_1
queue.items.lock('FOR UPDATE SKIP LOCKED').first # => item_2
However, with RSpec, any code I run in a Thread.new
can't find any record, something like:
let(:queue) { MyFancyQueue.create }
let!(:items) { create_list(:item, 2, queue: queue) }
context 'with first item locked' do
it 'returns the second item' do
Thread.new { queue.items.first.with_lock { sleep 30 } }
expect(queue.items.lock('FOR UPDATE SKIP LOCKED').first).to eq items.last
end
end
would throw an error saying queue.items.first
can't be found, and when using pry
to look into the thread, I can't see any items.
How do I effectively test something like this with RSpec?
If you use DatabaseCleaner
make sure DatabaseCleaner.strategy = :truncation
for this test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With