-
-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using ActiveJob async adapter (and threads in general) with before_all is risky #278
Comments
Yeah, the hack was added to support using async execution triggered right in the
I think, the possible solution could be is to override The same problem occurs if you're not using One option is to add a global config.after(:each) do
if ActiveJob::QueueAdapters::AsyncAdapter === ActiveJob::Base.queue_adapter
# shutdown previous instance, waits for in-flight tasks by default
ActiveJob::Base.queue_adapter.shutdown
# create a new one
ActiveJob::Base.queue_adapter = :async
end
end
Yeah, that would helpful |
Sure, but it wouldn't be noticeable since you wouldn't expect database state to carry over, so an async job "stealing" the last connection wouldn't matter much.
I tried this but it didn't work reliably. I think the issue is that the teardown that unsets Perhaps there's some way to force this job clearing hook to run first, before the lock_thread is unset, but I'm reaching the limits of my rspec knowledge here. |
It shouldn't. It's invoked by Rails in the However, it seems that there was a problem in |
I think the issue is that hooks defined at the suite level run after hooks defined in each example or context. It looks like rspec mixes in a module that invokes Maybe the answer here is to include a module that defines an after hook. But I'd say the tl;dr of all this is that it's complicated and probably deserves it's own caveat or some actual code that others can use directly for this scenario. I'd be happy to help out if you let me know which direction is best for this project. |
Yeah, seems so. I wonder if the problem is Looks the most robust way of dealing with it is to patch the ActiveRecord::TestFixtures.prepend(Module.new do
def teardown_fixtures
# do some cleanup
super
end
end) Note that this only would work in recent Ruby versions (prepending only included module has no effect in older versions) |
Tell us about your environment
Ruby Version: 3.2.2
Framework Version (RSpec, Minitest, FactoryGirl, Rails, whatever): RSpec 3.12, Rails 7.0.8
TestProf Version: 1.2.3
The docs could use a caveat about the dangers of using before_all with threading, in particular, using ActiveJob's async queue adapter.
The case I ran into was using before_all for system specs with the async queue adapter. While the test is running, things work well, but it's possible for a job to get executed after the test completes which can mess up the db connections and cause hard to debug failures.
During teardown, the
use_transactional_fixtures
functionality will unset thelock_thread
, so if after that point, an async job runs, it may grab the connection with the open transaction. If the next test starts before the job completes, a new connection will be used which means a fresh transaction without any fixture data.There's a comment that implies that the async adapter case is handled, but it doesn't account for Rails unsetting lock_thread in teardown.
Some ideas on how to improve this situation:
The text was updated successfully, but these errors were encountered: