fix(episode): coordinate frame cache extraction with filelock and safe staging - #635
sivasurya05 wants to merge 1 commit into
Conversation
|
👋 Hi @sivasurya05 — thank you so much for your first contribution to HFlow! A maintainer will review your pull request as soon as possible. In the meantime:
💡 Tip: one open pull request per contributor at a time. Before starting an issue, check its sidebar for an assignee or a linked pull request. Either one means somebody is already on it; everything else is fair game. We are excited to have you here and appreciate your help making the project better! 🙌 |
|
…nd safe staging - Use standard library fcntl.flock to coordinate concurrent workers across threads and processes, matching the existing _mirror_entry_lock pattern. - Fast-path cache hits so read-only working directories succeed without attempting to create directories or acquire lock files. - Stage extraction within isolated temporary directories and atomically publish via staging_directory.replace(output_directory). - Write a .hflow_staging marker in staging directories to safely identify and clean up stranded directories from killed workers on retry, while strictly preserving unrelated caller backup files and directories. - Add regression coverage in tests/test_frame_cache_concurrency.py.
aede263 to
120bbf9
Compare
Summary
Fixes race conditions and cache clobbering in
Episode.frames()andEpisode.frames_at_indices()under concurrent multi-threaded and multi-process runtimes (e.g., PyTorchDataLoader(num_workers > 1)andprefetch).Uses the standard library's
fcntl.flockand isolated staging directories to ensure safe cache extraction and publication, with zero new direct dependencies.Problems Addressed (#634)
Deterministic
.tmppath collisions: Both methods previously staged extracted frames using hardcoded paths (frames_{label}.tmpand<output_dir>.tmp). Concurrent workers extracting the same cache key could overwrite or delete each other's in-progress files.Cache deletion race in
frames_at_indices(): Uncoordinated cache checks could allow a lagging worker to executeshutil.rmtree(output_directory), deleting another worker's freshly completed cache.Unnecessary third-party locking dependency: Uses the built-in
fcntl.flock, following the existing_mirror_entry_lockpattern insrc/hflow/storage.py. HFlow targets POSIX runtimes, with Windows supported via WSL2.Read-only workdir support: Cache hits return immediately through a fast path, avoiding directory creation and lock file writes on read-only mounts.
Safe orphan cleanup: Abrupt worker termination (e.g.,
SIGKILLor OOM) can leave partial staging directories behind. Retries safely clean up these directories under the lock using an internal.hflow_stagingmarker, while preserving caller-owned backup files and directories matching<cache_key>.*.tmp.Changes Made
src/hflow/episode.py_frame_cache_staging(output_directory, is_cached)helper to coordinate cache extraction and publication.is_cached()is satisfied, avoiding unnecessary locking and filesystem writes.fcntl.flockon<output_dir>.lockto coordinate concurrent threads and processes..hflow_stagingmarker while holding the lock.tempfile.TemporaryDirectory(prefix=f"{name}.", suffix=".tmp", dir=parent)to create unique staging directories..replace(output_directory).Episode.frames()andEpisode.frames_at_indices()to use_frame_cache_staging.Dependencies
pyproject.tomloruv.lock.Test Coverage
Added regression tests in
tests/test_frame_cache_concurrency.py:test_concurrent_identical_requests_frames— Thread concurrency forframes().test_concurrent_identical_requests_frames_at_indices— Thread concurrency forframes_at_indices().test_separate_processes_coordination_frames— Multi-process coordination usingProcessPoolExecutorwith thespawncontext.test_separate_processes_coordination_frames_at_indices— Multi-process coordination for indexed frame extraction.test_failed_extraction_leaves_no_artifacts_and_retry_succeeds_frames— Failure cleanup and retry forframes().test_failed_extraction_leaves_no_artifacts_and_retry_succeeds_frames_at_indices— Failure recovery for indexed frame extraction.test_incomplete_indexed_cache_is_rebuilt_safely— Safe rebuilding of incomplete caches under the lock.test_cache_hits_succeed_in_read_only_workdir— Ensures cache hits work in read-only workdirs without lock acquisition.test_stranded_staging_directories_cleaned_up_on_retry— Verifies cleanup of orphaned staging directories.test_unrelated_backup_files_and_directories_are_preserved_on_cache_miss— Ensures unrelated caller-owned backup files and directories remain untouched.Related Issue
Closes #634