Skip to content

docs: document sqlx test connection limits#4278

Open
angelnereira wants to merge 1 commit into
transact-rs:mainfrom
angelnereira:docs/sqlx-test-concurrency
Open

docs: document sqlx test connection limits#4278
angelnereira wants to merge 1 commit into
transact-rs:mainfrom
angelnereira:docs/sqlx-test-concurrency

Conversation

@angelnereira

Copy link
Copy Markdown

Summary

  • document how #[sqlx::test] interacts with database connection limits when many tests run concurrently
  • show how to use the PoolOptions test signature to reduce the per-test pool size
  • mention cargo test -- --test-threads <N> as a way to limit Rust test runner concurrency

This is related to #2567.

Checks

  • cargo fmt
  • cargo test -p sqlx --doc --no-default-features --features postgres,macros,migrate,runtime-tokio
  • cargo check -p sqlx --no-default-features --features postgres,macros,migrate,runtime-tokio
  • git diff --check

@abonander

Copy link
Copy Markdown
Collaborator

The defaults for #[sqlx::test] are almost certainly suboptimal. It's different per driver, but Postgres is set to use 20 connections max for a single test binary and each test is allowed to acquire up to 5 connections.

That's effectively only 4 tests that are allowed to run concurrently if all tests try to use max_connections.

There's also the possibility of a dining philosopher's problem if each test needs multiple connections and manage to acquire some but not all of them, so they end up blocked each waiting for the other to release those connections so they can proceed. I wonder if that's what's causing a lot of PoolTimedOut errors.

Increasing max_connections may help but could also result in tests under cargo-nextest starting to fail because the coordination is entirely in-process, so multiple test binaries running concurrently would all think they're allowed to use the maximum.

The reason #3582 didn't make it into 0.9.0 is because I got stuck thinking about this exact problem, because I wanted to delete the pool inheritance mechanism that #[sqlx::test] uses but then that would require completely rearchitecting #[sqlx::test].

I was thinking each test should have a declared max_connections that it acquires in permits from a semaphore up-front, so each test is either blocked or guaranteed to proceed, which should eliminate the dining philosopher's problem. But we still have the multi-process issue.

We might need to coordinate this through the database somehow, like using another table to track running tests and their max_connections, but then if a test process aborts we'd possibly be left with records that aren't cleaned up. I think we could get something working with row-level locking, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants