Repository navigation
fix(jobs): judge refresh cleanup against the unrestricted key_source - #1595
dimitri-yatsenko wants to merge 2 commits into
Conversation
`Job.refresh(*restrictions)` narrowed key_source to add jobs and then reused the narrowed key_source in its cleanup step. Every job older than stale_timeout whose key fell outside the restriction therefore looked vanished and was deleted, including jobs reserved by other workers and error records. `populate(*restrictions, reserve_jobs=True)` calls refresh this way. Cleanup now checks keys against the unrestricted key_source; the restrictions still limit which jobs are added and re-pended. Success and error records whose key has left both key_source and the target (because the upstream row was deleted) are now removed on every refresh, whatever their age, instead of lingering until stale_timeout. Records of rows that still exist are kept. The age-based check for the other statuses, and stale_timeout=0 skipping it, are unchanged. Cleanup now issues one DELETE per step instead of an existence query and a DELETE for each key. Closes #1594. Part of #1577.
MilagrosMarin
left a comment
There was a problem hiding this comment.
Thanks for the clear write-up @dimitri-yatsenko — judging cleanup against the unrestricted key_source is the right fix for #1594, and limiting the restrictions to the add/re-pend steps is the correct split. I read #1577 too; 3a lines up with the stale_timeout=0 complaint there. I haven't run the suite locally — these come from reading the diff.
Requested changes
✅ src/datajoint/jobs.py:343 — the stale_timeout parameter still reads "Set to 0 to skip." With 3a that's no longer true: success and error records of vanished keys are removed whatever stale_timeout is. The *restrictions entry and the Notes section were updated; this one wasn't. Suggested:
stale_timeout : float, optional
Seconds after which jobs are checked for staleness.
Jobs older than this are removed if key not in key_source.
Default from ``config.jobs.stale_timeout``. Set to 0 to skip the
age-based check; the cleanup of success and error records whose
keys have left both key_source and the target runs regardless.
✅ Test docstring — see the inline comment on test_jobs_refresh.py.
Follow-up, not for this PR
3a keeps a record whose row still exists (Not(target.proj())); 3b judges on key_source alone, so the same record is removed once it passes stale_timeout. That divergence is pre-existing, and it belongs with the rest of #1577 in 2.4 rather than here — worth a line in the issue so the next reader doesn't take 3a's principle as global.
Before merge
On head f3d44e0 I see no workflow runs or check-runs through the API and the combined status is pending. Worth confirming CI before this lands, given it's one of the two data-loss fixes.
The restricted-refresh and restricted-populate cases, the re-pend ordering ahead of cleanup, and the move to one DELETE per step all read correct to me. Let me know if anything needs adjusting!
|
|
||
|
|
||
| def test_refresh_keeps_success_records_of_existing_rows(schema_by_backend): | ||
| """A success record stays while its row exists, even if its key leaves key_source.""" |
There was a problem hiding this comment.
| """A success record stays while its row exists, even if its key leaves key_source.""" | |
| """A fresh success record stays while its row exists, even if its key leaves key_source.""" |
The job isn't backdated here, so this covers the 3a path only. 3b judges vanished on key_source without 3a's Not(target.proj()) guard, so the same record is removed once it's older than stale_timeout — pre-existing behavior, not something this PR changes. "Fresh" keeps the docstring to what the test actually pins down.
Review follow-up: the stale_timeout entry still said 0 skips the cleanup, but the success and error records of keys that have left both key_source and the target are now removed whatever the timeout. The test for records of existing rows covers a fresh record only, and its docstring now says so.
|
Thanks, @MilagrosMarin. Pushed 6a1e171 with both suggestions; the same commit is on #1597.
|
Closes #1594. Part of #1577.
Job.refresh(*restrictions)narrowedkey_sourceto add jobs, then reused the narrowedkey_sourcein its cleanup step. Every job older thanstale_timeoutwhose key fell outside the restriction therefore looked vanished and was deleted, including jobs reserved by other workers and error records.populate(*restrictions, reserve_jobs=True)calls refresh this way.key_source. The restrictions still limit which jobs are added and re-pended.key_sourceand the target (because the upstream row was deleted) are removed on every refresh, whatever their age, instead of lingering untilstale_timeout. Records of rows that still exist are kept.stale_timeout=0skipping it. That is the rest of Jobs: with keep_completed, success and error records outlive the rows they describe #1577, which waits for 2.4.Tests:
tests/integration/test_jobs_refresh.py, on MySQL and PostgreSQL. It covers a restricted refresh, a restrictedpopulate, records of vanished keys, records of rows that still exist,stale_timeout=0, and the statement count. The jobs and autopopulate suites pass locally.The same commit goes onto
maint/2.3for the v2.3.5 patch release.