|
| 1 | +# Write Lifecycle & Latency Compensation |
| 2 | + |
| 3 | +This document details the lifecycle of a write operation (Set, Update, Delete) from the moment the API is called to when it is committed to the backend. It focuses on **Mutations**, **Overlays**, and how the SDK achieves instant **Latency Compensation**. |
| 4 | + |
| 5 | +## Key Concepts |
| 6 | + |
| 7 | +* **Mutation**: An operation that modifies a document (e.g., `SetMutation`, `PatchMutation`, `DeleteMutation`). |
| 8 | +* **Mutation Batch**: A group of mutations that must be applied atomically. Every user write creates a new Batch with a unique `BatchID`. |
| 9 | +* **Overlay**: A "Materialized View" of the changes applied to a document. Instead of re-calculating the result of a mutation every time a query runs, the SDK calculates the result *once* at write time and saves it as an Overlay. |
| 10 | + |
| 11 | +## Phase 1: Mutation Creation & Batching |
| 12 | + |
| 13 | +When a user calls `setDoc` or `updateDoc`: |
| 14 | +1. **Validation**: The SDK validates the data locally. |
| 15 | +2. **Batching**: The operation is wrapped in a `MutationBatch`. |
| 16 | +3. **Persistence**: The batch is serialized and saved to the `mutation_queue` table in IndexedDB. |
| 17 | + * **Partitioning**: Queues are partitioned by User ID. If the user is offline, these batches accumulate in the queue. |
| 18 | + |
| 19 | +## Phase 2: Overlay Calculation (Optimization) |
| 20 | + |
| 21 | +To ensure queries run fast, the SDK does not apply raw mutations to remote documents during every query execution. Instead, it pre-calculates the result. |
| 22 | + |
| 23 | +1. **Base State**: The SDK retrieves the current state of the document (from `remote_documents`). |
| 24 | +2. **Apply**: It applies the new `Mutation` to the base state to determine what the document *should* look like locally. |
| 25 | +3. **Persist Overlay**: This resulting state is saved to the `document_overlays` table. |
| 26 | + * **Field Mask**: The overlay tracks specifically which fields were modified. |
| 27 | +4. **Latency Compensation**: The `Event Manager` immediately triggers active listeners. The listeners read the `Overlay` instead of the `Remote Document`, giving the user the illusion of instant updates. |
| 28 | + |
| 29 | +> **Formula:** `Local View = Remote Document + Overlay` |
| 30 | +
|
| 31 | +## Phase 3: Synchronization (The Write Pipeline) |
| 32 | + |
| 33 | +The `SyncEngine` manages the flow of data to the server: |
| 34 | + |
| 35 | +1. **Filling the Pipeline**: The `RemoteStore` reads the `mutation_queue` in order of `BatchID` (FIFO). |
| 36 | +2. **Transmission**: Mutations are sent to the backend via gRPC (or REST in Lite). |
| 37 | +3. **Atomicity**: If a batch contains multiple writes, the backend guarantees they are applied together or not at all. |
| 38 | + |
| 39 | +## Phase 4: Acknowledgement & Cleanup |
| 40 | + |
| 41 | +When the backend responds: |
| 42 | + |
| 43 | +### Scenario A: Success (Ack) |
| 44 | +1. **Commit**: The backend commits the change and returns the authoritative version of the document (and transformation results, like server timestamps). |
| 45 | +2. **Update Remote**: The SDK updates the `remote_documents` table with this new server version. |
| 46 | +3. **Cleanup**: |
| 47 | + * The `MutationBatch` is removed from `mutation_queue`. |
| 48 | + * The corresponding `Overlay` is removed from `document_overlays` (since the Remote Document now matches the desired state). |
| 49 | +4. **Re-Evaluation**: Active queries are re-run. Since the Overlay is gone, they now read the updated Remote Document. |
| 50 | + |
| 51 | +### Scenario B: Rejection |
| 52 | +1. The `MutationBatch` is removed. |
| 53 | +2. The `Overlay` is removed. |
| 54 | +3. The Local View reverts to the `Remote Document` state (rolling back the optimistic update). |
0 commit comments