Repository navigation
fix(tests): stop Windows xdist workers from sharing DuckDB and sushi files - #6184
Conversation
- tests/core/engine_adapter/test_duckdb.py: three tests that call
duck_conn.install_extension("ducklake") now share the same
xdist_group("ducklake_extension"). On Windows, parallel xdist workers
all downloading and renaming the extension binary at once triggers
'Could not move file: Access is denied'. Grouping them forces the
three tests onto a single worker, so extension installation is always
sequential.
- tests/core/linter/test_helpers.py: both sushi-context tests now use
the copy_to_temp_path fixture instead of pointing directly at
examples/sushi. The shared .cache/optimized_query directory is
excluded by the copytree ignore rules, so each test gets its own
writable cache root and Windows file-lock contention is eliminated.
Signed-off-by: Nick Muoh <[email protected]>
Co-authored-by: Cursor <[email protected]>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
… locks On Windows, a loaded DuckDB extension (.dll) holds an OS file handle that blocks install_extension() from atomically moving the newly-downloaded file into place. The duck_conn fixture previously only returned the connection (no explicit close), relying on CPython reference-counting to tear it down between tests. With the adapter fixture holding the connection via a lambda closure, and pytest-xdist running three ducklake tests sequentially on the same worker, two stale connections can still hold the ducklake.dll open by the time the third test calls install_extension(), producing: _duckdb.IOException: IO Error: Could not move file: Access is denied. Change the fixture to yield + conn.close() so the connection — and any DLLs it has loaded — is fully released before the next test begins. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
Windows keeps ducklake.dll mapped after the connection closes, so a later test's install_extension cannot move the file into place. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
A fixture loads DuckLake once per test without a second install call while the DLL is still mapped, which on Windows causes 'Access is denied' when install_extension tries to move ducklake.dll. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
|
The sushi Blocking
Non-blocking
The 3.9 failure ( |
2514d48 to
b7aa915
Compare
duckdb_extensions().installed can report false on a new connection after an earlier connection in the same process loaded the DLL, so the install still ran and Windows denied the file move. Install only when load fails. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
Windows CI showed load_extension failing with a transient "Failed to create directory ~/.duckdb" error, after which the install fallback hit the already-loaded DLL. Never install from the fixture; LOAD auto-installs when missing, and Windows CI installs DuckLake before pytest. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
Closing the connection does not unload extension DLLs, so the yield/close change did not help the Windows DuckLake failure. Signed-off-by: Nick Muoh <[email protected]> Co-authored-by: Cursor <[email protected]>
Description
Two Windows CI flakes, both from tests sharing files on disk. This unblocks #6176.
DuckLake. Once a process loads DuckLake, its DLL stays loaded until the process exits; closing the connection does not unload it. Any later
install_extension("ducklake")in that process replaces the file on disk, which Windows refuses withCould not move file: Access is denied. Guarding the install did not help: in run 41899285609,load_extensionin the second DuckLake test failed withFailed to create directory "C:\Users\runneradmin\.duckdb": Cannot create a file when that file already exists, even though the first test had just installed DuckLake there, and the install fallback then hit the loaded DLL. So the tests no longer install at all.LOADauto-installs DuckLake when it is missing (local runs, Linux, macOS), and the Windows job installs it before pytest.The transient
~/.duckdberror itself is not explained. Most likely another xdist worker is writing to the shared~/.duckdbat the same moment. If it comes back, it now surfaces as that error instead of "Access is denied".Sushi cache. The two linter tests wrote
examples/sushi/.cachein the repo, and parallel workers collided on it. They now run on a temp copy.Roughly 40 other tests still construct
Contextdirectly onexamples/sushiand share that cache. This PR only isolates the two that failed. Worth a follow-up if more of them flake on Windows.Test Plan
test_drop_table_ducklake_no_cascade_mixed_case_aliasfailed (Access is denied) andtest_get_range_of_a_key_in_model_block_testing_on_sushifailed (Permission denied on the sushi cache).close()(run 41478055750), aduckdb_extensions().installedcheck (run 41636441149), and load-then-install (run 41899285609). The sushi cache failure did not return after the first commit. The installed-check code also passed once (run 41750858262), so one green run is not conclusive on its own.duck_connintests/conftest.pyto main.load_extension("ducklake")against an emptyextension_directoryauto-installs it. Linux and macOS can't reproduce the Windows failure.Merge danger: two-way door, revert the commits. Blast radius is CI only; these are test and CI-workflow changes, and production engines are unchanged.
Checklist
make styleand fixed any issuesmake fast-test)git commit -s) per the DCO