Swap: retry a journal's recovery checkpoint while idle
After a lost record the journal drops position-based records until a full checkpoint. That checkpoint was only requested from later edits, rate-limited to once a second; when the writer handled the failing record before its edit asked for a checkpoint, the checkpoint failed as well and consumed the slot, so edits made within the next second were not recovered and, if the user stopped typing, the journal stayed behind indefinitely. SwapManager::RetryGapCheckpoints(), called once per frame from Editor::ProcessPendingOpens, requests it once the interval has passed. This also made SwapReplay_LostRecord_ResyncsWithCheckpoint flaky under load; the test now exercises the retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
@@ -1172,6 +1172,27 @@ SwapManager::maybe_request_checkpoint(Buffer &buf, const std::size_t approx_edit
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SwapManager::RetryGapCheckpoints()
|
||||
{
|
||||
std::vector<Buffer *> due;
|
||||
{
|
||||
std::lock_guard<std::mutex> lg(mtx_);
|
||||
const std::uint64_t now = now_ns();
|
||||
for (auto &[b, ctx]: journals_) {
|
||||
if (!b || !ctx.gap || ctx.suspended || ctx.locked_out || ctx.gap_unfixable_reported)
|
||||
continue;
|
||||
if (now - ctx.gap_chkpt_request_ns < kGapCheckpointIntervalNs)
|
||||
continue;
|
||||
ctx.gap_chkpt_request_ns = now;
|
||||
due.push_back(b);
|
||||
}
|
||||
}
|
||||
for (Buffer *b: due)
|
||||
RecordCheckpoint(*b, false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SwapManager::RecordCheckpoint(Buffer &buf, const bool urgent_flush)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user