Skip to content

Update the test history under a lock, in batches of finished tests - #188

Merged
giordano merged 8 commits into
mainfrom
mg/history-lock-merge
Sep 20, 2026
Merged

giordano merged 8 commits into
mainfrom
mg/history-lock-merge

Conversation

@giordano

@giordano giordano commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation for this is that I'm moving Oceananigans to ParallelTestRunner and we use self-hosted runners which share the depot. The idea is to make the accesses to the history file safe.

History files are updated not just at the end of the tests but every 20 finished tests to save intermediate progress for large test suites, and also not to entirely lose the data in case the test driver process is abruptly terminated without a chance of finishing things up cleanly.

Ref: #187

@giordano
giordano added this pull request to stack #190 September 19, 2026 19:55
Comment thread src/ParallelTestRunner.jl Resolved
@giordano
giordano force-pushed the mg/history-lock-merge branch from ac48ad8 to ae5d541 Compare September 20, 2026 09:17

@christiangnrd christiangnrd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conceptually LGTM, I glanced at the implementation but I can take a closer look if you would like me to. Can probably be merged as a stack with #189?

giordano and others added 8 commits September 20, 2026 18:46
The history of durations and failures was read once at the start of
`runtests` and the whole in-memory copy was serialized back at the end,
so of several runs sharing a machine the last to finish overwrote what
the others had recorded, and a reader could see a half-written file.

Finished tests are now merged into the file under a
`FileWatching.Pidfile` lock, re-reading the stored history first, and
the file is replaced through a temporary file and rename. Entries of
tests a run did not execute are left untouched, and a lock left behind
by a dead process is removed right away. Outcomes are written in
batches of `history_flush_every` tests (and once more at the end), so
the lock and rename traffic stays low on slow filesystems while an
interrupted run still keeps all but its last few measurements. Fixes
#187 (first proposal).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNK7qXSraxSfzK6T4UxUtk
How many finished tests to accumulate before merging them into the
on-disk history trades lock and rename traffic against how much an
interrupted run can lose, and the right balance depends on where the
scratch space lives. Expose it as a documented keyword with the same
default of 20 instead of a module-level variable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNK7qXSraxSfzK6T4UxUtk
@giordano
giordano force-pushed the mg/history-lock-merge branch from 81b06f9 to b682d53 Compare September 20, 2026 17:46
@giordano
giordano merged commit 3c3250f into main Sep 20, 2026
18 checks passed
@giordano
giordano deleted the mg/history-lock-merge branch September 20, 2026 18:03
@giordano

Copy link
Copy Markdown
Collaborator Author

BTW, if you still have a chance to give this a closer look, I'd appreciate it! It should be decent though, and it has all the locks (on the filesystem and in process) where I was expecting them. Still, happy to know whether I missed something!

@giordano giordano linked an issue Sep 20, 2026 that may be closed by this pull request
@christiangnrd

Copy link
Copy Markdown
Collaborator

Claude found this while I was asking about something else:

One behavioral difference worth knowing about. Retries interact with batching in a way the old code did not have. Every attempt of a test is recorded, and nothing removes a name from the opposite set. So if a test fails, is retried, and passes before the batch is flushed, it sits in both failed and passed of the same batch. The merge applies the removal first and the union second, so the test ends up marked as failed even though its last attempt passed. If the failing attempt happened to be flushed in an earlier batch, the retry batch only contains it in passed and it is correctly cleared. Before the change, the history was built from the final results list, where a retry replaced the earlier attempt, so a test that passed on retry was always removed from the failure set. There is no test covering retries together with history, so this went unnoticed.

I'll add a fix for it with my PR moving the code over to a file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

History files are overwritten by concurrent builds

2 participants