Configure parallel tests in rails app (which doesn't work - yet)#78
Configure parallel tests in rails app (which doesn't work - yet)#78zcotter wants to merge 2 commits intotemporalio:mainfrom
Conversation
|
|
Reproduces temporalio/samples-ruby#78: when a process forks after a Temporal runtime is created (e.g., Rails parallelize) and the child exits with `exit` (triggering Ruby's object finalization), the Rust Drop for CoreRuntime tries to shut down Tokio, which wakes the I/O driver using inherited (now invalid) kqueue/epoll FDs — causing a panic: "failed to wake I/O driver: Bad file descriptor". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. | ||
| fixtures :all | ||
|
|
||
| parallelize(workers: :number_of_processors, threshold: 1) |
There was a problem hiding this comment.
This doesn't work due to us not supporting using native backed Ruby structures across forks: https://ruby.temporal.io/#forking
This can be worked around by setting up a Temporal::Client for each process.
| parallelize(workers: :number_of_processors, threshold: 1) | |
| parallelize(workers: :number_of_processors, threshold: 1) | |
| # Create a fresh runtime and client in each forked worker, | |
| # connecting to the same dev server started in the parent. | |
| parallelize_setup do |_worker| | |
| TemporalClient.instance = Temporalio::Client.connect( | |
| TemporalClient.server_target, | |
| 'default', | |
| runtime: Temporalio::Runtime.new, | |
| logger: Rails.logger | |
| ) | |
| end |
Note, this requires adding server_target getter/setter on the TemporalClient module in this sample.
There was a problem hiding this comment.
Thanks for the quick response @chris-olszewski ! I tried your sample code with parallelize_setup and I'm still encountering a few other issues:
- RuntimeError: Client already set
- Temporalio::Internal::Bridge::Error: Cannot create worker across forks (original runtime PID is 74216, current is 74376)
- The test suite freezes before finishing until i kill it
I pushed up the changes I made in case I got lost on the server_target implementation. Appreciate your help!
There was a problem hiding this comment.
Ah, I apologize. I accidentally was using a build of the gem where I was leaking all of the native owned resources (which avoids the issue in a very dumb way).
The Temporalio::Testing::WorkflowEnvironment creates a new Runtime which can't be shared across processes, so that in addition to the client need to be setup per process.
e.g.
parallelize_setup do |_worker|
@temporal_test_env = Temporalio::Testing::WorkflowEnvironment.start_local(logger: Rails.logger)
TemporalClient.instance = @temporal_test_env.client
end
parallelize_teardown do |_worker|
@temporal_test_env&.shutdown
end
And remove the module level test server start (and the temporal_client.rs changes are no longer necessary).
I realize this isn't great as you're starting a dev server per-process, but it should prevent sharing any native backed objects across forks.
Reproduces temporalio/samples-ruby#78: when a process forks after a Temporal runtime is created (e.g., Rails parallelize) and the child exits with `exit` (triggering Ruby's object finalization), the Rust Drop for CoreRuntime tries to shut down Tokio, which wakes the I/O driver using inherited (now invalid) kqueue/epoll FDs — causing a panic: "failed to wake I/O driver: Bad file descriptor". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> squash
* Add failing test for fork + process exit Tokio panic Reproduces temporalio/samples-ruby#78: when a process forks after a Temporal runtime is created (e.g., Rails parallelize) and the child exits with `exit` (triggering Ruby's object finalization), the Rust Drop for CoreRuntime tries to shut down Tokio, which wakes the I/O driver using inherited (now invalid) kqueue/epoll FDs — causing a panic: "failed to wake I/O driver: Bad file descriptor". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> squash * fix: avoid cleaning up tokio in forked children * empty to retrigger cla
Hello! Our apps use parallel tests in rails to make the test suite finish faster. See rails docs here: https://api.rubyonrails.org/classes/ActiveSupport/TestCase.html#method-c-parallelize
However, it seems this is not compatible with the temporal test_helper.rb setup documented in this repo. See error output below when I run tests with the test suite configured to run tests in parallel (they pass without my code change so I know its not an environment issue, etc). How can we get temporal running along with parallel tests?
Thanks for your help!