Avoid SQLite stalls from connection setup and stderr span logging (#49032)

## Why

Setting `auto_vacuum` on every connection can wait for a writer lock even when the mode is unchanged. Logging every span entry and exit can also block SQLx workers on undrained stderr while they hold a write transaction.

## What changed

- Set incremental vacuum only for empty databases or databases using full auto-vacuum, before enabling WAL. Preserve existing nonempty databases with auto-vacuum disabled.
- Emit span creation and closure events in app-server text and JSON stderr logs, preserving busy/idle timings and explicit events while omitting span entry and exit records.

## Testing

Add regression tests for opening and expanding writable pools while another connection holds a writer lock, and for transaction completion with undrained stderr in both log formats. Verify vacuum modes and retained log diagnostics.

GitOrigin-RevId: 40d4ef32c7efc49f4240b987277ba45551259335
This commit is contained in:
jif
2026-09-28 17:00:25 +00:00
committed by copyberry
parent d8fc718809
commit 46fdd5ef39
4 changed files with 238 additions and 6 deletions
+28 -4
View File
@@ -16,9 +16,7 @@ use sqlx::ConnectOptions;
use sqlx::Error;
use sqlx::SqlitePool;
use sqlx::migrate::Migrator;
use sqlx::sqlite::SqliteAutoVacuum;
use sqlx::sqlite::SqliteConnectOptions;
use sqlx::sqlite::SqliteJournalMode;
use sqlx::sqlite::SqlitePoolOptions;
use sqlx::sqlite::SqliteSynchronous;
use std::path::Path;
@@ -299,13 +297,39 @@ impl SqliteConfig {
let options = SqliteConnectOptions::new()
.filename(path)
.create_if_missing(true)
.journal_mode(SqliteJournalMode::Wal)
.synchronous(SqliteSynchronous::Normal)
.auto_vacuum(SqliteAutoVacuum::Incremental)
.busy_timeout(Duration::from_secs(5))
.log_statements(LevelFilter::Off);
SqlitePoolOptions::new()
.max_connections(5)
.after_connect(|connection, _metadata| {
Box::pin(async move {
let mode: i64 = sqlx::query_scalar("PRAGMA auto_vacuum")
.fetch_one(&mut *connection)
.await?;
// The setter takes the writer lock even when the mode is unchanged.
// Initialize it before WAL creates the first database page. Existing
// NONE databases require VACUUM to convert; leave those alone.
let empty = if mode == 0 {
sqlx::query_scalar::<_, bool>(
"SELECT NOT EXISTS (SELECT 1 FROM sqlite_schema)",
)
.fetch_one(&mut *connection)
.await?
} else {
false
};
if mode == 1 || empty {
sqlx::query("PRAGMA auto_vacuum = INCREMENTAL")
.execute(&mut *connection)
.await?;
}
sqlx::query("PRAGMA journal_mode = WAL")
.execute(connection)
.await?;
Ok(())
})
})
.connect_with(options)
.await
}