fix(services): writes wait for Delete All before they queue; restores replace only settled lists

Delete All, third variant: a write that arrived after Delete All waited
for it inside its playlist's queue. A Stalker repair that reserved that
playlist meanwhile skipped the barrier, but its write still queued
behind that waiting one, while the reset waited for the repair's
reservation. While a Delete All runs, writes now wait for it before they
join their queue, so no queue holds work blocked on the reset; a write
under a reservation held here joins at once.

A restore replaced lists while this page's own write for the playlist
was still unsent (refused, or lost): that write's edits joined the
replacement and a conflict replay kept items the backup did not have.
Both restore paths now require the playlist's writes to be on the
server first (flushed), and otherwise stay parked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-10-14 21:28:13 +02:00
1 parent dd143c8aca
commit 6e44aef3c8
9 files changed
+180 -26

No files matched your search

+4 -2
View File
@@ -268,8 +268,10 @@ settings and guards read them in every build.
first (`ready(true)`: another device may have changed the lists since) and
fails when that read does not succeed: unread maps would export as empty lists, and a restore's lists
would merge into the server's instead of replacing them (the restore
stays parked). A restore also counts only once the server took that
playlist's lists (`UserDataStorage.flushed`); a refused one stays parked. Replayed edits keep recently viewed lists newest first,
stays parked). A restore also replaces nothing while this page's own
writes for the playlist are unsent (they would join the replacement) and
counts only once the server took its lists (`UserDataStorage.flushed`);
either way it stays parked. Replayed edits keep recently viewed lists newest first,
as the app cuts them at their limit from the end. Also,
re-reads run one at a time and keep entries edited while they were in
flight or not yet saved, and entries another tab saved meanwhile or had
+4 -2
View File
@@ -244,8 +244,10 @@ reservation stays held through its conditional row transform. The reservation
blocks every new authentication (including a URL edit with the same normalized
fingerprint) and repair, and drains any work already in flight. Delete All
drains the playlist writes queued before it, then takes the exclusive reset;
later writes wait for the delete, except a write under a reservation this tab
holds (`holdsPlaylistAuthority`), which the reset waits for in turn.
later writes wait for the delete before they join their playlist's queue, so
no queue holds work blocked on the reset, except a write under a reservation
this tab holds (`holdsPlaylistAuthority`), which joins at once since the
reset waits for that reservation.
When Save follows a lazy repair in the same tab, Edit publishes its local
authentication owner first, drains that repair through the actual Web Lock
request completion, and only then requests the row reservation itself. Repair