Skip to content

Commit 5e4e7ba

Browse files
committed
fix: serialize ducklake extension install in tests
DuckDB's INSTALL command replaces the extension file on disk, which races when multiple test threads call it concurrently. Use std::sync::Once to ensure the extension is installed exactly once per test binary. Fixes flaky test_concurrent_metadata_access failure on Ubuntu CI.
1 parent eb0eaa4 commit 5e4e7ba

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

tests/common/mod.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010

1111
use anyhow::Result;
1212
use std::path::Path;
13+
use std::sync::Once;
14+
15+
static INSTALL_DUCKLAKE: Once = Once::new();
16+
17+
/// Install the ducklake extension exactly once (thread-safe across parallel tests).
18+
fn ensure_ducklake_installed() {
19+
INSTALL_DUCKLAKE.call_once(|| {
20+
let conn = duckdb::Connection::open_in_memory().expect("open in-memory duckdb");
21+
conn.execute("INSTALL ducklake;", [])
22+
.expect("install ducklake extension");
23+
});
24+
}
1325

1426
/// Creates a catalog with a simple table (no deletes)
1527
///
@@ -29,7 +41,7 @@ pub fn create_catalog_no_deletes(catalog_path: &Path) -> Result<()> {
2941
// Use in-memory database to avoid file locking issues
3042
let conn = duckdb::Connection::open_in_memory()?;
3143

32-
conn.execute("INSTALL ducklake;", [])?;
44+
ensure_ducklake_installed();
3345
conn.execute("LOAD ducklake;", [])?;
3446

3547
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -69,7 +81,7 @@ pub fn create_catalog_with_deletes(catalog_path: &Path) -> Result<()> {
6981
// Use in-memory database to avoid file locking issues
7082
let conn = duckdb::Connection::open_in_memory()?;
7183

72-
conn.execute("INSTALL ducklake;", [])?;
84+
ensure_ducklake_installed();
7385
conn.execute("LOAD ducklake;", [])?;
7486

7587
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -115,7 +127,7 @@ pub fn create_catalog_with_updates(catalog_path: &Path) -> Result<()> {
115127
// Use in-memory database to avoid file locking issues
116128
let conn = duckdb::Connection::open_in_memory()?;
117129

118-
conn.execute("INSTALL ducklake;", [])?;
130+
ensure_ducklake_installed();
119131
conn.execute("LOAD ducklake;", [])?;
120132

121133
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -170,7 +182,7 @@ pub fn create_catalog_filter_pushdown(catalog_path: &Path) -> Result<()> {
170182
// Use in-memory database to avoid file locking issues
171183
let conn = duckdb::Connection::open_in_memory()?;
172184

173-
conn.execute("INSTALL ducklake;", [])?;
185+
ensure_ducklake_installed();
174186
conn.execute("LOAD ducklake;", [])?;
175187

176188
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -208,7 +220,7 @@ pub fn create_catalog_filter_pushdown(catalog_path: &Path) -> Result<()> {
208220
pub fn create_catalog_empty_table(catalog_path: &Path) -> Result<()> {
209221
let conn = duckdb::Connection::open_in_memory()?;
210222

211-
conn.execute("INSTALL ducklake;", [])?;
223+
ensure_ducklake_installed();
212224
conn.execute("LOAD ducklake;", [])?;
213225

214226
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -238,7 +250,7 @@ pub fn create_catalog_empty_table(catalog_path: &Path) -> Result<()> {
238250
pub fn create_catalog_basic_test(catalog_path: &Path) -> Result<()> {
239251
let conn = duckdb::Connection::open_in_memory()?;
240252

241-
conn.execute("INSTALL ducklake;", [])?;
253+
ensure_ducklake_installed();
242254
conn.execute("LOAD ducklake;", [])?;
243255

244256
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -290,7 +302,7 @@ pub fn to_datafusion_error(e: anyhow::Error) -> datafusion::error::DataFusionErr
290302
pub fn create_catalog_complex_deletions(catalog_path: &Path) -> Result<()> {
291303
let conn = duckdb::Connection::open_in_memory()?;
292304

293-
conn.execute("INSTALL ducklake;", [])?;
305+
ensure_ducklake_installed();
294306
conn.execute("LOAD ducklake;", [])?;
295307

296308
let ducklake_path = format!("ducklake:{}", catalog_path.display());
@@ -336,7 +348,7 @@ pub fn create_catalog_complex_deletions(catalog_path: &Path) -> Result<()> {
336348
pub fn create_catalog_multiple_snapshots(catalog_path: &Path) -> Result<()> {
337349
let conn = duckdb::Connection::open_in_memory()?;
338350

339-
conn.execute("INSTALL ducklake;", [])?;
351+
ensure_ducklake_installed();
340352
conn.execute("LOAD ducklake;", [])?;
341353

342354
let ducklake_path = format!("ducklake:{}", catalog_path.display());

0 commit comments

Comments
 (0)