mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
docs(chord): slice 8 review 2 fixes; design §17 and slices folded
This commit is contained in:
parent
02a2b2532d
commit
eb9d443462
3 changed files with 24 additions and 19 deletions
|
|
@ -1497,7 +1497,7 @@ export default defineFacet((host, self) => { // `self` (contributions) a
|
|||
export const Http = defineRegistry<HttpContribution, Router>("chord.http", { version: 2 }); // shared: identity only
|
||||
host.serve(Http, { // the defining plugin's facet: the one provider (slice 8 D1)
|
||||
compose: (table, { report }) => buildRouter(table, report), // pure; always delivers a value; reports conflicts
|
||||
accepts: { 1: (old: HttpContributionV1): HttpContribution => upgrade(old) },
|
||||
accepts: { 1: { contribution: (old: HttpContributionV1) => upgrade(old), value: (router) => routerV1(router) } },
|
||||
});
|
||||
self.contribute(Http, { routes: { … }, wraps: [ … ] });
|
||||
const router = self.registry(Http).value; // live (host.registry(Http) outside objects)
|
||||
|
|
@ -1535,6 +1535,12 @@ const router = self.registry(Http).value; // live (host.registry(Http) outsi
|
|||
use site catches synchronous throws and rejections when it calls an entry, reports naming the contributor (the
|
||||
composed table keeps each entry's plugin name), and continues with the other entries. Durable already does this for
|
||||
extensions (`extension_error`; a throwing tool becomes an error result); `compose` reports through `report`.
|
||||
- **Slice 8's rules** (decisions "Slice 8 D1" to "Slice 8 S3", `slice-8.md`): the token is shared, the provider serves it
|
||||
(`host.serve(R, { compose, accepts })`); `self.registry(R)` in a factory is a declared dependency (activation waits
|
||||
for a value; with none after `load`, the reader fails `transient` and is retried when one arrives); contributions
|
||||
never fail a registry (a failed one is left out and reported); a throwing `compose` keeps the last good composition;
|
||||
older readers get the value mapped back (`accepts[old].value`); `retryOn` retries on value calls only; `host.root(fn,
|
||||
context, { principal? })` seals its context at settle, abort and `host.close`.
|
||||
- **Registries may carry natives.** An entry lives exactly as long as its contributor; consumers look up at each use
|
||||
or follow the composed value and keep nothing from an entry beyond a use.
|
||||
- **Contributions that change (owner, 2026-10-19; W4):** registries are host-local, so contributions are usually
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ await host.root(async (ctx) => (await ctx.get(Notes, { session })).add(note, ctx
|
|||
order); a contribution carries its token's version: an older one is adapted once with the declaration's `accepts`
|
||||
when the table is built, an older one without an adapter or a newer one is left out and reported (`HostError`
|
||||
`contribution_refused { registry, plugin, version }`).
|
||||
- **Contributions:** a plain value, or a Chord watchable (a `writable`, a derive, a document member, another
|
||||
registry's value), followed as a dependent of the table (its change recomposes); a foreign watchable (a Durable watch)
|
||||
- **Contributions:** a plain value, or a Chord watchable (a `writable`, a derive, a document member; another
|
||||
registry's value too, a cycle of registries reading each other refused when the second one serves or contributes), followed as a dependent of the table (its change recomposes); a foreign watchable (a Durable watch)
|
||||
is refused at `contribute` (declaration policy). The table's entry is `{ plugin, type?, version, value }` (`type` for
|
||||
an object contributor; served types carry their plugin's name).
|
||||
- **`compose(table, { report })`:** pure, lazy as a derive: the registry's value is marked when its table changes (a
|
||||
|
|
@ -83,9 +83,11 @@ await host.root(async (ctx) => (await ctx.get(Notes, { session })).add(note, ctx
|
|||
table; its serve composes it.
|
||||
- **Reading is a dependency (S3, owner, 2026-10-27: "isn't self.registry meant to wait like self.get?"):**
|
||||
`self.registry(R)` in a factory declares the registry as a dependency of the attempt, as `self.get`: activation waits
|
||||
until it has a value (bounded by `readyTimeout`); without one in time the object fails `transient` with
|
||||
`unavailable/undeclared` as the dependency's cause and is retried the moment the registry gets its first value
|
||||
(R18). It returns a `RegistryValue<V>` (a native source: a derive source, an `on` source, a `retryOn` source; never a
|
||||
until it has a value; once `load`'s setups ran, a registry with no value cannot get one before a reload (a provider
|
||||
comes only with a plugin), so a reader then fails at once `transient` with `unavailable/undeclared` as the
|
||||
dependency's cause (as `self.get` of a type not served here fails at once, and the start barrier waits for no
|
||||
contribution) and is retried the moment the registry gets its first value (R18); a first `compose` that throws fails
|
||||
its readers the same way. It returns a `RegistryValue<V>` (a native source: a derive source, an `on` source, a `retryOn` source; never a
|
||||
state member); methods and routines read `.value` at use. Once the object is live, a later failure of the registry
|
||||
(a throwing `compose`) changes nothing for it: `.value` keeps the last good composition. Code outside objects:
|
||||
`await host.registry(R, ctx)` waits the same way.
|
||||
|
|
@ -145,7 +147,8 @@ after `host.close` rejects `released`. No span of its own until slice 9.
|
|||
|
||||
- Durable's `HarnessOptions.registry` takes a `RegistryReader` (`snapshot()`, `subscribe(listener)`, the listener
|
||||
called synchronously after every publication). A `RegistryValue` offers a synchronous observer of its compositions
|
||||
(`observe(observer)`, as Durable's `observeXXX`: `advance` inside the flush that composed, record only); Durable's
|
||||
(`observe(observer, ctx)`, as Durable's `observeXXX`: `advance` inside the flush that composed, record only; an
|
||||
attached observer counts as watching, so the lazy compose runs for it); Durable's
|
||||
`registryReader(value)` (in its `src`) reads `.value` in `snapshot()` and forwards `observe` to `subscribe`. The
|
||||
harness object declares the extensions registry with `self.registry(...)`, so it activates (and opens Durable) only
|
||||
once the registry has a value. p3's `compose` builds Durable's snapshot without throwing (a duplicate task name is
|
||||
|
|
@ -155,15 +158,17 @@ after `host.close` rejects `released`. No span of its own until slice 9.
|
|||
|
||||
```ts
|
||||
const harness = self.registry(HarnessRegistry); // a dependency: activation waits for it
|
||||
self.retryOn(harness); // the new harness's contribution wakes the failed follower
|
||||
const view = self.follow((observer, ctx) => harness.value.observeConversation(id, observer, ctx));
|
||||
```
|
||||
|
||||
When that harness closes, Durable ends the observer `failed` (S1, a Durable change in this slice: a Session close
|
||||
ends observers `failed`, `ended` only when the observed owner ended), so the follower fails `transient` and its retry
|
||||
follows the new harness.
|
||||
- Example `29-registries.ts` (a router registry with two contributing plugins, a conflict reported, a `writable`
|
||||
contribution, a missing declaration healing); example `30-host-root.ts`; example `31-harness-registry.ts` (a
|
||||
Durable harness on the store, its extensions from a registry, its views followed by a second object).
|
||||
- Examples: Chord's `29-registries.ts` (a router registry with two contributing plugins, a conflict reported, a
|
||||
`writable` contribution, a missing provider healing) and `30-host-root.ts`; Durable's `test/examples/37-harness-
|
||||
registry.ts` (a Durable harness on the store, its extensions from a registry, its views followed by a second object)
|
||||
and the `registryReader` tests in Durable's tree.
|
||||
|
||||
## 6. Carry-over
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Order (owner, 2026-10-22: routines and jobs before the store and reload).
|
|||
| 6a | **The store** | the store (backends, tables, queries, writes, commit queue, outbox, documents engine, migrations, export), persisted documents, `self.table`, keyed watches and retirement |
|
||||
| 6b | **Durable and jobs on the store** | persisted jobs, Durable's `StoreStorage`, the Chord source over Durable's views (`self.follow`) |
|
||||
| 7 | **Reload and rollout** | plugin loading, staging, swaps and restarts, revisions, `accepts` in use |
|
||||
| 8 | **Registries and `host.root`** | registries, `self.writable`, `retryOn`, a `RegistryReader` for Durable, `host.root` and `chord(fn, context)` (the harness object is p3's base code) |
|
||||
| 8 | **Registries and `host.root`** | registries, `self.writable`, `retryOn`, a `RegistryReader` for Durable, `host.root` (`chord(fn, context)` and the harness object are p3's base code) |
|
||||
| 9 | **Telemetry** | spans, events, metrics across hosts |
|
||||
|
||||
The playground (`apps/chord-playground`) moves to the new code once slice 4 exists. Round-3 cuts (C3-C16) and
|
||||
|
|
@ -227,14 +227,8 @@ Specified in `slice-6b.md` (decided 2026-10-27, D1-D9, R1-R4, "owner names and c
|
|||
- **Durable's views from other objects** (from slice 6b): the harness carried in a registry entry, so an object other
|
||||
than the one that opened Durable can `self.follow` its views.
|
||||
|
||||
- **`host.root(fn, context, { principal? })`**: a call scope for code outside objects, built with its first users
|
||||
(Durable hooks, `chord(fn, context)`); decide what an aborted, uncooperative `fn` means for its references (match
|
||||
the handler and `CallContext` rules). (Slice 3b, owner.)
|
||||
- **`retryOn`** retries a broken object as `ref.retry()` does. (Slice 2.)
|
||||
- **`host.activity` on the facet's host** (`FacetHost`), if the harness or a core facet needs it; today only
|
||||
`references` is there. (Slice 4b.)
|
||||
- Registries recompose inside the owner's flush, never inside another owner's commit step; changing contributions are
|
||||
native watchables (`self.writable`). (W4.)
|
||||
- Specified in `slice-8.md` (decided 2026-10-27): `host.root` (D3), `retryOn` (D2), registries recomposing in the
|
||||
owner's flush (W4); `host.activity` on the facet's host dropped (nothing needs it).
|
||||
|
||||
### Slice 9: telemetry
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue