Skip to content

Commit d6a52ab

Browse files
id alloc rules
1 parent 76a6be5 commit d6a52ab

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

docs/wg/feat-crdt/id.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,43 @@ For offline scenarios, a simplified approach allows clients to create and edit d
7171

7272
This approach trades the need for deterministic offline actor IDs for simplicity, at the cost of requiring a local rewrite phase before the first sync. The rewrite is O(n) in the number of locally-created nodes but avoids the complexity of coordinating persistent offline actor identities across devices. Actor ID 0 serves as a clear marker for "not yet synced" content.
7373

74+
### Strict ID Allocation Rules (Avoid Minting)
75+
76+
These rules formalize **when an ID may be minted**. They minimize counter consumption without compromising CRDT safety.
77+
78+
**A. Allocate only at commit points**
79+
- Mint an object ID **only when the action is committed** (e.g., pointer-up for shape creation, Enter/blur for text, confirmed paste/import).
80+
- Do **not** mint during transient states (pointer-down, drag preview, rubber-band, hover, marquee, lasso, ghost handles, or scrubbers).
81+
82+
**B. No-mint zones (transient UI)**
83+
- Selections, transforms-in-progress, outline/guide overlays, resize handles, and measurement tools must use **ephemeral runtime handles** (not object IDs).
84+
- Undoable previews within a single gesture (e.g., dragging to decide size) reuse the same transient instance and only mint on commit.
85+
86+
**C. Reuse ephemeral scaffolding**
87+
- For tools that show a provisional object (e.g., a rectangle while dragging), reuse a **single ephemeral object** without an ID.
88+
- On commit, **materialize** it as a real object and mint the ID exactly once.
89+
90+
**D. Batch creation & import preflight**
91+
- Before a mass paste/import, compute the prospective count `N`. If `remaining(node_counter) < N`, request/rotate to a **new least-used actor id** *before* minting.
92+
- Batch-mint IDs in memory and write them atomically with the content to avoid partially minted states.
93+
94+
**E. Guardrails & rotation**
95+
- Define a soft threshold: when `node_counter >= 2^24 - MARGIN` (e.g., `MARGIN = 1_000_000`), automatically rotate to a fresh least-used actor id for future creations.
96+
- Emit telemetry/alert when threshold is crossed (per document, per actor).
97+
98+
**F. No recycling, ever**
99+
- Deleted/GC’d objects **do not free** `(actor,node)` pairs. Gaps are expected and harmless.
100+
- Never attempt to fill holes. Recycling risks collisions with late/replayed ops.
101+
102+
**G. Local collision detection & retry**
103+
- If a rare conflict on `(actor,node)` is detected on insert (e.g., due to offline merges), **retry with `node+1`** under the same actor (or rotate if near threshold). This maintains monotonic semantics without freelists.
104+
105+
**H. Presentation-only ordinals**
106+
- If dense numbering is needed for UI, compute **presentation ordinals** (1..k) over a stable sort (e.g., created time). Do not persist or sync these; keep the real ID as the only persistent identity.
107+
108+
**I. Observability**
109+
- Track per-actor counters, per-actor mint rates, and rewrite counts (offline→online) to validate that consumption is balanced and within expected bounds.
110+
74111
## Resource IDs (Out of Scope)
75112

76113
This ID model applies to **canvas objects and nodes only**. Resource identity (images, fonts, and other binary blobs) is handled separately through a content-addressable hash-based mechanism documented in [feat-hash-nch](../feat-hash-nch/index.md). Resource IDs are derived from content hashing and do not require actor-specific allocation, making them inherently collision-free and suitable for offline-first workflows without coordination.

0 commit comments

Comments
 (0)