fix: detect stale pipeline jobs by progress - #190
Open
Marquis03 wants to merge 1 commit into
Open
Conversation
Marquis03
marked this pull request as ready for review
August 19, 2026 09:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #189.
Problem and reproduction
The post-market pipeline was marked as failed after a fixed 20-minute wall-clock timeout even while it was still reporting progress.
Two observed adjustment-factor sync runs were cancelled after 1,282 and 1,336 seconds. Their latest progress messages were
41/139and50/139batches respectively, demonstrating that the jobs were slow but not stalled. This prevented large initial synchronizations from completing and delayed later stages such as ETF data preparation.Root cause
JobStore.reap_stale()measured elapsed time fromstarted_at. The normal 1,200-second timeout therefore applied to total job runtime rather than inactivity.The stale path also released the heavy-run lock even though the worker thread could not be forcibly stopped. Retrying could allow the previous worker and a new job to write the same data concurrently.
Solution
last_progress_atto active jobs.started_atfor active jobs created without the new field.failedatomic under the job-store lock.Compatibility
The new job field is additive. Existing job data without
last_progress_atcontinues to usestarted_at, and no API field is removed or renamed. Data-provider, Parquet, financial-data, and frontend contracts are unchanged.If a worker is permanently stuck, the job is marked failed but the execution slot remains unavailable until the process is restarted. This is an intentional fail-closed behavior to prevent concurrent writes.
Performance
Each progress callback performs one UTC timestamp update. Stale checks remain O(1), and no data-path scans or network calls are added.
Validation
python -m pytest tests/test_pipeline_and_monitor_fixes.py -q— 12 passed.git diff --checkpassed.UI evidence
No UI behavior or layout changed.
Risk and rollback
The remaining risk is a provider call that blocks longer than its job inactivity threshold without emitting progress. Such a worker will fail closed and require a backend restart before another heavy data task can begin.
The change can be rolled back by reverting this commit; no data migration is required.