Skip to content

fix(dashboard): keep a save that lands while a refresh is reading the store - #569

Merged
BryanFRD merged 1 commit into
mainfrom
fix/access-refresh-race
Oct 10, 2026
Merged

BryanFRD merged 1 commit into
mainfrom
fix/access-refresh-race

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #568

refresh_one reads the saved file, awaits, then applies the result. A save (or reset) from the dashboard that completes in that gap was overwritten by the refresh's older read.

  • Authorizer now counts explicit changes (revision, bumped by set_access). A refresh records the revision before it reads and applies through refresh_access(seen, access), which does nothing if the counter moved. A refresh's own apply does not bump it, so one refresh never makes the next give up.
  • A skipped refresh is logged at debug; the next tick reads the file again and converges.

Tests are deterministic and need no timing: a refresh nobody overtook applies; a save between the read and the apply is kept; a refresh does not move the counter; each explicit change does; with authentication disabled there is nothing to refresh.

I could not reproduce the race on Windows (the integration test passes 60 of 60 here), so the existing forge_access test is the check that matters, and it runs in this PR's CI. Full workspace tests pass locally.

@BryanFRD
BryanFRD enabled auto-merge (squash) October 10, 2026 15:52

@ferrfleet ferrfleet Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fix is correct. set_access bumps the revision while it holds the write lock, and refresh_access checks it under the same lock, so the check and the swap are atomic. seen is read before read_meta. A dashboard write or reset runs write_meta/delete_meta and then set_access, so any save that overlaps a refresh moves the counter and the refresh's result is dropped. If the refresh already read the new file, dropping it changes nothing. write and reset are the only callers of set_access, and both are explicit changes. Nothing blocking.

@BryanFRD
BryanFRD merged commit f22571c into main Oct 10, 2026
27 checks passed
@BryanFRD
BryanFRD deleted the fix/access-refresh-race branch October 10, 2026 15:56
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.

A save can be overwritten by a refresh that was already reading the store

1 participant