Repository navigation
Files: recover pending deletes after process death #503
Description
Problem
The Files delete write fence added in #498 keeps in-flight deletes and refresh-required blocks in memory, owned per account for the life of the app process. If the process dies after a DELETE reaches the server but before its outcome is recorded and verified, the restarted app starts with no block for that path. Cached Files content can still show the item, and writes (rename, move into, upload into, edit) can then target a path whose server state is unknown.
The window is narrow (process death between sending the DELETE and recording its verified outcome), but the result is an ambiguous non-idempotent mutation with no durable recovery path, which AGENTS.md sections 7, 8 and 10 rule out for durable mutation paths.
Raised in review of #498 (thread on FileWriteFence.kt). It was deliberately kept out of that PR, which documents the in-memory limitation in ADAPTER_ARCHITECTURE.md ("Files delete write fence").
Proposed direction
- Before sending a DELETE, persist an account-scoped pending-delete record: the local account identity (non-secret digest), remote path, server file ID and ETag when known, item type, and a request generation.
- On startup and account activation, reconcile each record before enabling writes for the affected path:
- re-register the refresh-required block;
- verify the postcondition with a server listing that starts after startup;
- clear the record only on a verified outcome.
- Clear the record on a verified outcome, and drop all records for an account on sign-out or account removal.
- Keep the existing lifting rule (only a server listing that started after the outcome lifts a block) and the identity rules (file ID, type, ETag).
Acceptance criteria
- A pending-delete record is durable before the request can leave the client, on desktop and Android.
- After a simulated process death at each stage (before send, after send but before response, after response but before verification), the restarted app blocks writes to that path with the typed refresh-required reason until verified.
- Records are scoped to the local account identity, contain no credentials or raw server URLs, and are removed on sign-out and account removal.
- Unknown or corrupt records fail closed (path stays blocked until verified) and are bounded in count.
- Deterministic restart, cancellation, stale-generation, and account-removal tests; Android unit tests execute.
-
ADAPTER_ARCHITECTURE.mdand the changelog no longer say a new process starts unblocked.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity