mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
docs(chord): slice 6b D4, the store has Durable's Storage semantics
This commit is contained in:
parent
cc12dad236
commit
a9181321a0
3 changed files with 32 additions and 18 deletions
|
|
@ -1648,6 +1648,17 @@ validation and copies the v2 kernel added around Delta.
|
|||
"document ids monotonic with seq". Durable's own ids still rise in its creation order (its Session line serializes
|
||||
its commits and mints inside them), which its scans, transcripts and windows rely on; Chord's ids are gaps between
|
||||
them, as the five record types already leave. A minted id never committed may come again after a reopen (S10).
|
||||
- **Slice 6b D4: the store has Durable's Storage semantics (owner, 2026-10-27: "agreed"; supersedes in part "Store
|
||||
errors: Durable's rule" and slice-6a rule 10's "an expression result outside it fails the step, which is
|
||||
`storage_failed`"):** Durable has two levels: its `Storage` rolls a failed commit back and stays usable (the
|
||||
conformance suite tests it), its Session fails on any commit error (`GuardedStorage`). "Store errors: Durable's
|
||||
rule" had put the Session's level into the store. Now: a step that fails before `COMMIT` rolls back and rejects that
|
||||
commit only (the step's code runs in the transaction callback, so an error there is known to come before `COMMIT`);
|
||||
the store stops only when the outcome is unknown (`COMMIT` or `ROLLBACK` failed), when `adopt` threw, or on a read's
|
||||
backend error. Owners react as Durable's Session: Durable's Session fails (unchanged); a Chord object whose commit the
|
||||
step refused fails live (`object_failed`, `broken`: memory and disk disagree); an `int` `CHECK` failure (a plugin's
|
||||
value out of range) fails only that transaction (`invalid/args`). `StoreStorage` runs Durable's commit checks in the
|
||||
step, where `SqliteStorage` runs them: no special case. Built in 6b (the store's step and object failure).
|
||||
- **The performance and memory bar, and converging reviews (owner, 2026-10-27: "yes"):** supersedes "as good as
|
||||
HEAD in everything" for Chord v2 slices and pi changes. CPU: each hot path (calls, changes, watches, links) within
|
||||
about 5% of HEAD, measured in bursts with alternating processes pinned to one CPU; worse is fixed or goes to the
|
||||
|
|
|
|||
|
|
@ -894,9 +894,9 @@ host.serve(DraftStore, (_, self) => { // local, empty params: may
|
|||
storage batch through the store's commit step, `await store.commit(writes, adopt, ctx)` without the caller's abort
|
||||
signal (deltas, or a base when `checkpointWhen` says so; the line held until the step returned, as Durable's
|
||||
`#runCommit`, owner, 2026-10-26); adopt by pointer swap and mark dependents in the step, persisted and in-memory
|
||||
documents and staged changes in one `host.batch.commit` (any backend error in the step is `storage_failed`,
|
||||
Durable's rule, owner, 2026-10-26: plugin mistakes are refused when a write is staged; a seal-fenced commit is
|
||||
rejected `released` before `BEGIN`); then the owner's synchronous flush recomputes dirty derives, sends one message
|
||||
documents and staged changes in one `host.batch.commit` (errors as Durable's Storage, owner, 2026-10-27: a step that
|
||||
fails before `COMMIT` rolls back and rejects that commit only, nothing adopted, the store goes on; plugin mistakes are
|
||||
refused when a write is staged; a seal-fenced commit is rejected `released` before `BEGIN`); then the owner's synchronous flush recomputes dirty derives, sends one message
|
||||
per link and queues watch callbacks (W1); drafts then throw if touched. In-memory-only commits take no store seq and never
|
||||
enter the commit queue (W12). No
|
||||
revalidation of the whole document, no copy, no freeze.
|
||||
|
|
@ -1077,10 +1077,15 @@ host.serve(DraftStore, (_, self) => { // local, empty params: may
|
|||
runtime has it, otherwise a `MessageChannel` message (2026-10-27, slice 6a build reviews).
|
||||
- **Eviction as in Durable,** for keyed persisted documents only (persisted singletons and `at(key)` documents stay
|
||||
in memory while their object lives: `handle.value` is a synchronous read; owner, 2026-10-26): one not read, written or watched for the retention
|
||||
period (default 10 minutes) leaves memory and reloads on the next access. A storage error ends the store and closes
|
||||
the host; `onError` receives `{ kind: "storage_failed" }` and the app decides (section 3). Any backend error in a
|
||||
commit step, or on a read whose `ctx` was not aborted, is a storage error (Durable's rule); later calls reject
|
||||
`unavailable/storage_failed`.
|
||||
period (default 10 minutes) leaves memory and reloads on the next access. **Store errors (owner, 2026-10-27; supersedes in part "Store errors: Durable's rule"):** the store has Durable's
|
||||
`Storage` semantics, its owners react as Durable's Session does. A step that fails before `COMMIT` rolls back: that
|
||||
commit rejects, nothing is adopted, the store goes on. The store stops (`storage_failed`: later calls reject
|
||||
`unavailable/storage_failed`, the host closes, `onError` receives `{ kind: "storage_failed" }`, the app decides,
|
||||
section 3) only when the outcome is unknown (`COMMIT` or `ROLLBACK` failed) or `adopt` threw, and on a backend
|
||||
error of a read whose `ctx` was not aborted. A Chord object whose commit the step refused (memory and disk disagree:
|
||||
the counted conditional `UPDATE`, the live-address index) fails live (`object_failed`, `broken`); an `int` result out
|
||||
of range (`CHECK`) fails only that transaction (`invalid/args`). Durable's Session fails on any commit error
|
||||
(`GuardedStorage`), as today.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -71,10 +71,8 @@ kinds and keys) keep Durable's JSON encoding in their columns.
|
|||
orders, the fork chain walked as `SqliteStorage` does), `task`, `scanTasks`, `submission`, `scanSubmissions`,
|
||||
`submissionByRequest`, `scanConversations`: queries over the declared tables, Durable's cursors (`{ after, order }`,
|
||||
`scan.ts`) kept as they are (built from the last id, not from Chord's table cursors).
|
||||
- **Validation before the step** (D4 below): what `SqliteStorage` checks inside its transaction
|
||||
(`checkGlobalIds`, `prepareDocumentActions`, `checkDocumentActions`) runs before `store.commit`, with plain reads:
|
||||
only Durable's Session writes these tables and it serializes its commits, so the reads see the state the step will
|
||||
write on (the argument of S11).
|
||||
- **Validation in the step** (D4): what `SqliteStorage` checks inside its transaction (`checkGlobalIds`,
|
||||
`prepareDocumentActions`, `checkDocumentActions`) runs inside the store's step, which rolls back a refused commit.
|
||||
|
||||
### 1.2 IDs
|
||||
|
||||
|
|
@ -115,13 +113,13 @@ scope as a string (`session`, `conversation:7`, `task:31`), kind and key JSON-en
|
|||
- **Durable's seq is the store's seq** (gaps allowed: Chord's commits take seqs too).
|
||||
- **Errors:**
|
||||
|
||||
> **Decision needed (D4): what a refused Durable commit does to the store.** The store's rule: any backend error in a
|
||||
> step is `storage_failed`, the store stops (Durable's own rule for its Session). Durable's conformance suite commits
|
||||
> invalid batches on purpose ("ID 1 already belongs to conversation", "already has a current incarnation", "version
|
||||
> transition requires a base", a mismatched copy) and expects the storage to go on. Proposal: those checks run before
|
||||
> the step (1.1) and reject there, the store untouched; only a backend failure inside the step stops the store. In
|
||||
> production the Session fails on any commit error either way (`GuardedStorage`), so the difference is only that the
|
||||
> store, shared with Chord's objects, does not stop for a Durable bug caught by its checks.
|
||||
**Errors (D4, owner, 2026-10-27):** the store takes Durable's `Storage` semantics (design §10 "Store errors"): a
|
||||
step that fails before `COMMIT` rolls back and rejects that commit only; the store stops only on an unknown outcome
|
||||
(`COMMIT` or `ROLLBACK` failed), a throwing `adopt`, or a read's backend error. Owners react as Durable's Session:
|
||||
Durable's Session fails (`GuardedStorage`, unchanged); a Chord object whose commit the step refused fails live
|
||||
(`object_failed`, `broken`); an `int` `CHECK` failure fails only its transaction (`invalid/args`). `StoreStorage` runs
|
||||
Durable's commit checks in the step, as `SqliteStorage` does, so the conformance suite's refused commits leave the
|
||||
store usable. 6b changes 6a's step and object failure accordingly.
|
||||
|
||||
- `mintId`, `close(context)` (closes nothing of the store: the app owns it; later calls reject "closed"), reads after
|
||||
a store failure reject as Durable's `GuardedStorage` expects.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue