fix(preprocess): anchor DWH retention validation

This commit is contained in:
2026-07-12 06:15:27 +02:00
parent 27697e5db2
commit 4a29086fe4
2 changed files with 127 additions and 25 deletions
+65
View File
@@ -260,6 +260,71 @@ def test_corrupt_newer_directory_does_not_consume_rollback_slot(tmp_path):
assert corrupt.is_dir()
def test_retention_n_counts_active_plus_n_minus_one_rollbacks_even_if_active_is_old(tmp_path):
import os
run_ids = []
pipeline = None
for index in range(3):
pipeline = DwhPreprocessPipeline(
workspace_id="demo", workspace_root=tmp_path,
config_fingerprint=FP, input_fingerprint=FP,
introspect=lambda output, i=index: output.write_text(str(i)),
build_lsh=lambda physical, output, i=index: [
(output / name).write_text(str(i))
for name in ("demo_lsh.pkl", "demo_minhashes.pkl", "demo_meta.json")
], retain_generations=3,
)
run_ids.append(pipeline.run().run_id)
generations = tmp_path / ".tht-dwh" / "generations"
os.utime(generations / run_ids[-1], ns=(1, 1))
pipeline.retain_generations = 2
pipeline._cleanup_generations()
remaining = {path.name for path in generations.iterdir() if path.is_dir()}
assert remaining == {run_ids[-1], run_ids[-2]}
def test_retention_candidate_swap_to_symlink_is_never_followed(monkeypatch, tmp_path):
import tht.jobs.dwh_pipeline as module
pipeline = DwhPreprocessPipeline(
workspace_id="demo", workspace_root=tmp_path,
config_fingerprint=FP, input_fingerprint=FP,
introspect=lambda output: output.write_text("active"),
build_lsh=lambda physical, output: [
(output / name).write_text("active")
for name in ("demo_lsh.pkl", "demo_minhashes.pkl", "demo_meta.json")
], retain_generations=1,
)
pipeline.run()
generations = tmp_path / ".tht-dwh" / "generations"
candidate_name = "e" * 32
candidate = generations / candidate_name
candidate.mkdir(mode=0o700)
external = tmp_path / "external-crafted"
external.mkdir()
sentinel = external / "sentinel"
sentinel.write_text("must-not-read-or-mutate")
real_open = module.os.open
swapped = False
def swapping_open(path, flags, *args, **kwargs):
nonlocal swapped
if path == candidate_name and kwargs.get("dir_fd") is not None and not swapped:
swapped = True
candidate.rmdir()
candidate.symlink_to(external, target_is_directory=True)
return real_open(path, flags, *args, **kwargs)
monkeypatch.setattr(module.os, "open", swapping_open)
pipeline._cleanup_generations()
assert swapped
assert sentinel.read_text() == "must-not-read-or-mutate"
assert candidate.is_symlink()
def test_reader_lease_blocks_retain_one_publisher_until_file_reads_finish(tmp_path):
import threading
import time