Skip to content

fix(persistence): rearm read retries for later edits - #433

Merged
chhoumann merged 3 commits into
masterfrom
fix/rearm-read-retry
Oct 13, 2026
Merged

chhoumann merged 3 commits into
masterfrom
fix/rearm-read-retry

Conversation

@chhoumann

@chhoumann chhoumann commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

After a temporary read outage, reverting the last edit or rolling back a failed import could stop retries permanently. Later edits stayed in memory and were lost on quit, even after the disk recovered.

Background edits now re-arm the existing retry only under the runtime unreadable-file refusal, with a loaded document and pending work. Startup refusals stay blocked, idle writes stay at zero, and attempts retain the 10-second cadence. The refused-background-save test now catches the surviving Notice mutation, and the failed-read catch explains why it retries.

Refs #426. Deferred schema retries and the missing newer-schema Notice are tracked in #429. Strict import/API-key recovery is tracked in #430. Review also identified existing visibility-flush and startup-Notice cases, filed as #431 and #432. These stay outside this final persistence PR.

Verification

  • Both F1 regressions fail on master: the reverted-edit route leaves disk at 15 instead of 33; the import-rollback route omits the later-added feed. The refused-background mutation fails on an extra generic Notice. Startup protection and cadence are covered.
  • Obsidian 1.14.4/Linux, isolated worktree vault: real Settings controls reproduce both stranded routes on master; the branch saves the later edit and clears the sticky Notice. No feed or audio fixture is needed. Each route makes one recovery write and no idle writes. Normal count:writes matches master exactly (two writes, 3966 bytes).
  • npm run lint, npm run format:check, npm run typecheck, npm run build, npm run test, npm run test:tooling, npm run docs:build, npm run test:e2e, and npm run size: all passed. Application tests: 1740; tooling: 10; E2E: 77 (one full run, Obsidian 1.14.4/Linux). Final bundle: 285622 raw / 90884 gzip bytes, +175 / +28 versus master.
  • Report and repeatable probes, logs, hashes, and screenshots. Independent GPT/Claude reviews: no introduced correctness blockers; existing findings are filed as the issues above.
Route Master after recovery, disk remains 15 Branch after recovery, disk saves 33
Revert last edit Master retains the read refusal Branch clears the refusal
Import rollback Master retains the read refusal after rollback Branch saves the later edit after rollback

The screenshots show memory at 33 in both versions. The linked probe logs verify the persisted values.

Release impact

No schema, settings shape, encoding boundary, API, or migration changes.

Docs at release

Document that a new Settings edit resumes saves after a temporary read outage, including when earlier edits were reverted or an import was rolled back.

Note

Rearm persistence retries for edits after a failed data.json read

  • Adds DataFileWriter.retryPending in writer.ts, which schedules a checkpoint retry when a readable base document exists and a failed write or unsaved edits are pending. It does nothing before a file is loaded or when nothing is pending.
  • PodNotes.saveSettings in main.ts now calls retryPending when the refusal reason is unreadable-data-file. Other refusal reasons still do not retry.
  • Repeated retryPending calls coalesce into one timer, which writes only the latest in-memory value at the checkpoint deadline.
  • Adds integration coverage for read-recovery saves, unload-time flushes during Obsidian shutdown, older-version synced refusals, and settings-import rollback recovery.

Macroscope summarized 34c910f.

…g pending

Undoing every pending edit during a read outage, or rolling back an import
whose save could not read data.json, stops the read retry. Edits made once
the file reads again never reach disk. Both routes fail on the current
writer. The unload test now also covers a refused background write, which
must show no failure Notice, and the startup refusal test attaches its
writer after loading, as onload does.
…its are undone

While data.json could not be read at runtime, saveSettings dropped every
request, and only the writer's read retry could lift the refusal. That retry
stopped once nothing was pending, as after undoing every edit or rolling back
a failed import, so edits made after the file read again stayed in memory and
were lost on quit.

saveSettings now hands a request under that refusal to the writer's new
retryPending, which arms the existing checkpoint retry when a loaded file has
pending work. The retry keeps its 10 s spacing, arms nothing while nothing is
pending, and still arms nothing under the startup refusal, before any file was
loaded. The other refusals still drop requests.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying podnotes with  Cloudflare Pages  Cloudflare Pages

Latest commit: 34c910f
Status: ✅  Deploy successful!
Preview URL: https://e46acbe2.podnotes.pages.dev
Branch Preview URL: https://fix-rearm-read-retry.podnotes.pages.dev

View logs

@chhoumann
chhoumann merged commit edb9447 into master Oct 13, 2026
15 checks passed
@chhoumann
chhoumann deleted the fix/rearm-read-retry branch October 13, 2026 01:53
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.

1 participant