Public Access
Sync: after a read from the beginning, remove what the server no longer has, and flag an edit that brings a forgotten item back
The server now forgets a deletion past its retention and refuses cursors from before it. The client then reads everything again, but everything again says nothing about what went. So a machine away for longer than the retention kept those items for good, and its next edit of one put it back on the server for everyone. A read from the beginning now marks each item it reads, keeping the mark in the sync state because the read can span passes. When it finishes, it removes the items of the synced types it never marked. Two kinds are kept: items newer than the read's bound, which this machine pushed during it, and items with a change still waiting, which are the user's work. For those, the push finds the server without the item and sends it as a create, as before, but now records a RecreatedAfterCollection conflict and counts it, so the sync message says so instead of undoing someone's deletion silently. The bound is the highest sequence the cache held when the read began, or anything higher it has read since. Taking only what the read returned would have left the last item of a vault in place for ever.
This commit is contained in:
1 parent
55e5de0ce4
commit
858e36279d
13 files changed
+1048
-63
No files matched your search
@@ -68,7 +68,15 @@ the Npgsql connection string** — the default; do not enable multiplexing.
|
||||
visible conflicted copy for opaque ones. **It must never silently drop a key or a host.**
|
||||
- Deletes are revisioned tombstones, garbage-collected after 90 days. Sync must therefore be
|
||||
able to read tombstones, which is the one place that legitimately bypasses the soft-delete
|
||||
query filter — guarded by an explicit permission check.
|
||||
query filter — guarded by an explicit permission check. **The collection has since been built**
|
||||
(`TombstoneCollector`), and it costs a machine away for longer than the retention its news of
|
||||
those deletions. So a collection raises the vault's sync horizon, and a cursor from before it is
|
||||
refused. The client then reads from the beginning, and when that read finishes it removes the
|
||||
items it held that the read never mentioned. An item with an unsent local edit is kept: the
|
||||
push finds the server without it, puts it back, and records a `RecreatedAfterCollection`
|
||||
conflict. A cursor carries the horizon it was issued under. Without that, the read from the
|
||||
beginning would be refused on its own early pages, which sit behind the horizon whenever an
|
||||
older item survives.
|
||||
- **An `Infrastructure.Tests` case must prove cursor ordering under N concurrent pushes.**
|
||||
Without it this ADR's central bug is invisible until production.
|
||||
- Two concurrency mechanisms, deliberately: `version integer` is the client-visible monotonic
|
||||
|
||||
Reference in new issue
Block a user