Skip to content

Make SyncStateStore map updates atomic - #120

Merged
in-jun merged 1 commit into
mainfrom
fix/syncstatestore
Jul 18, 2026
Merged

Make SyncStateStore map updates atomic#120
in-jun merged 1 commit into
mainfrom
fix/syncstatestore

Conversation

@in-jun

@in-jun in-jun commented Jul 18, 2026

Copy link
Copy Markdown
Owner

SyncStateStore.record() and forget() performed a plain read-modify-write on the shared _lastSync MutableStateFlow map. record() runs on worker/service dispatcher threads while forget() runs on the main thread from MainViewModel.deletePair, and the two aren't serialized against each other, so concurrent writers could read the same old map and silently clobber one another's change.

  • Replace both _lastSync.value = _lastSync.value ... assignments with _lastSync.update { ... } so the read-modify-write is atomic against concurrent writers.

Fixes #52

@in-jun in-jun left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmed the race this targets: record() is called from SyncManager on worker/service dispatcher threads while forget() runs from MainViewModel.deletePair on the main thread, and the two plain _lastSync.value = _lastSync.value ... assignments weren't serialized against each other, so concurrent writers could read the same map and clobber one another.

Switching both to _lastSync.update { ... } fixes this cleanly — the CAS retry loop makes each read-modify-write atomic against concurrent writers, which is exactly the primitive this needs. These two assignments are the only non-atomic map updates in the class, so the fix is complete. Leaving the prefs.edit().apply() calls as-is is correct: SharedPreferences handles its own concurrency and those values self-heal on the next load anyway.

Minimal and well-targeted. Looks good.

@in-jun
in-jun merged commit af28c0b into main Jul 18, 2026
1 check passed
@in-jun
in-jun deleted the fix/syncstatestore branch July 18, 2026 16:04
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.

Sync state map is updated non-atomically from multiple threads

1 participant