docs(chord): dependency model: hostAddress wording

This commit is contained in:
Mario Zechner 2026-10-29 07:44:21 +00:00
parent 373fbcc706
commit aee933269b
2 changed files with 14 additions and 12 deletions

View file

@ -169,11 +169,12 @@ host. For a `remote` type, the consumer computes the address from the params wit
`hostAddress` function (design §3; `placement` until 2026-10-29): `Notes { session: "S1" }` is placed on `Session { id: "S1" }`. If that is this host's
address, the request goes here; otherwise over the route for that kind, or over the parent link.
Today the code checks something else first: whether the type is registered here. A type placed on this host but not
registered yet is sent over the parent link, which is wrong twice. Sol's example: the server has address `Server`,
the catalog type is placed on `Server`, and no facet serves it yet. Today's `Placement.reference` (`host/placement.ts`) sends the server's
own request over a parent link the server never had. And when the catalog plugin is installed later, nothing wakes
that request, because it was never registered as waiting here.
Until 2026-10-29 the code checked something else first: whether the type is registered here. A type placed on this host but not
registered yet was sent over the parent link, which is wrong twice. Sol's example: the server has address `Server`,
the catalog type is placed on `Server`, and no facet serves it yet. That code, `Placement.reference` (`host/placement.ts`, now `host/destination.ts`), sent the server's
own request over a parent link the server never had, and when the catalog plugin was installed later, nothing woke
that request, because it was never registered as waiting here. The rename removed the first half; slice 7 builds the
wait.
:::flow wide | The destination by address. The destination follows from the address alone; only then is the provider found there checked.
row "Where" accent
@ -1076,7 +1077,7 @@ The Rule column cites sections of the working document, reproduced in appendix C
| # | Scenario | Under the model | Today | Rule |
| --- | --- | --- | --- | --- |
| 1 | `self.get(NoteStore)` in `Notes { S1 }`'s factory on W1; `NoteStore` is served and activating. | `Notes` makes its request, it binds to the `NoteStore` object, `Notes` parks `loading`. `NoteStore` goes live: a target state change wakes `Notes`, which opens its natives and goes live. No timer ran. | The same wait, bounded by `readyTimeout`; past it `Notes` fails `transient` and backs off (`attempt.ts` `waitFor`). | §3.1, §3.4, §4 |
| 2 | `self.get(Catalog)` from W1's `ForwardStore`; the parent link is up, S has published, `Catalog` is served there. | The request goes over the parent (placement `Server()`); S binds the hold; `bound` arrives; `ForwardStore` was `loading`, now goes on and live. | The same, after S's whole barrier (`Hold.start` awaits `pendingLoad`). | §1, §2 |
| 2 | `self.get(Catalog)` from W1's `ForwardStore`; the parent link is up, S has published, `Catalog` is served there. | The request goes over the parent (`hostAddress: () => Server()`); S binds the hold; `bound` arrives; `ForwardStore` was `loading`, now goes on and live. | The same, after S's whole barrier (`Hold.start` awaits `pendingLoad`). | §1, §2 |
| 3 | The same, but `Catalog`'s plugin is not installed on S. | S indexes the hold `not_served` under "p2.catalog" and answers `failed { waiting, not_served }`; `ForwardStore`'s reference shows `failed { waiting }`, the object parks `failed { waiting, "waiting for p2.catalog: not served" }`. A reload on S serving `Catalog` re-runs the hold: `loading`, `bound`; the reference goes live, the dependent wakes. No backoff, no new hold. | The hold is refused `broken`; `ForwardStore` fails `transient` and re-holds every 1-60 s, refused each time (`remote/hold.ts` `#refuse`, `object.ts` backoff). | §1, §3.1, §4, §5 |
| 4 | `self.get(SessionInfo)` on W1 when the core facet is missing (same host, not served). | The request is unbound `not_served` on W1 itself; the dependent parks `failed { waiting }`; a reload serving the type binds it and wakes the dependent. | `#assertRoute` throws in the factory: the object is `broken` until `retry()` or a reload (`host.ts` `reference`). | §1, §3.1, §4 |
| 5 | A tab's `NotesView` declares `Notes { S1 }`; S routes `Session`, `resolve` forks W1, W1 connects and publishes. | The hold waits at T on its path (`no_link` while S resolves: `loading`), is relayed to W1, waits there `unpublished` until W1's setups, then binds; `bound` comes back through the relay. `NotesView` was `loading` the whole time and goes live. | The same chain of waits, each bounded by `readyTimeout`; a slow worker start past it fails the tab object `transient` and polls. | §1, §6.2 |

View file

@ -316,11 +316,12 @@ and a reload that removes a type sends <code>gone</code>. Both go.</p>
host. For a <code>remote</code> type, the consumer computes the address from the params with its own contract&#39;s
<code>hostAddress</code> function (design §3; <code>placement</code> until 2026-10-29): <code>Notes { session: &quot;S1&quot; }</code> is placed on <code>Session { id: &quot;S1&quot; }</code>. If that is this host&#39;s
address, the request goes here; otherwise over the route for that kind, or over the parent link.</p>
<p>Today the code checks something else first: whether the type is registered here. A type placed on this host but not
registered yet is sent over the parent link, which is wrong twice. Sol&#39;s example: the server has address <code>Server</code>,
the catalog type is placed on <code>Server</code>, and no facet serves it yet. Today&#39;s <code>Placement.reference</code> (<code>host/placement.ts</code>) sends the server&#39;s
own request over a parent link the server never had. And when the catalog plugin is installed later, nothing wakes
that request, because it was never registered as waiting here.</p>
<p>Until 2026-10-29 the code checked something else first: whether the type is registered here. A type placed on this host but not
registered yet was sent over the parent link, which is wrong twice. Sol&#39;s example: the server has address <code>Server</code>,
the catalog type is placed on <code>Server</code>, and no facet serves it yet. That code, <code>Placement.reference</code> (<code>host/placement.ts</code>, now <code>host/destination.ts</code>), sent the server&#39;s
own request over a parent link the server never had, and when the catalog plugin was installed later, nothing woke
that request, because it was never registered as waiting here. The rename removed the first half; slice 7 builds the
wait.</p>
<figure class="fig wide"><svg viewBox="0 0 720 231" width="100%" role="img" aria-label="The destination by address. The destination follows from the address alone; only then is the provider found there checked." xmlns="http://www.w3.org/2000/svg" style="font-family:'Avenir Next','Helvetica Neue',Helvetica,Arial,sans-serif;max-width:760px"><defs><marker id="f2m" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#7b7468"/></marker><marker id="f2a" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#b4472f"/></marker><marker id="f2b" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#2e6a8a"/></marker></defs><text x="16" y="22" font-size="10" fill="#b4472f" text-anchor="start" font-weight="600" letter-spacing="2">WHERE</text><text x="16" y="144" font-size="10" fill="#7b7468" text-anchor="start" font-weight="600" letter-spacing="2">THEN</text><rect x="19" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#b4472f" stroke-width="1.5"/><text x="124" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">the request's address</text><text x="124" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">from the consumer's own `hostAddress`</text><rect x="255" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#c9bfae"/><text x="360" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">here</text><text x="360" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">a local type, or this host's address</text><rect x="491" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="596" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">a route or the parent</text><text x="596" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">every other address</text><rect x="137" y="158" width="210" height="55" rx="4" fill="#fff" stroke="#c9bfae"/><text x="242" y="176.5" font-size="11" fill="#2a2723" text-anchor="middle">check the provider here</text><text x="242" y="190.5" font-size="9.5" fill="#7b7468" text-anchor="middle">served? fitting version? authorize,</text><text x="242" y="203" font-size="9.5" fill="#7b7468" text-anchor="middle">own host address</text><rect x="373" y="158" width="210" height="55" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="478" y="176.5" font-size="11" fill="#2a2723" text-anchor="middle">hold over the path</text><text x="478" y="190.5" font-size="9.5" fill="#7b7468" text-anchor="middle">the provider host checks it the same</text><text x="478" y="203" font-size="9.5" fill="#7b7468" text-anchor="middle">way</text><path d="M229 58 L253 58" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M124 32 Q360 -12 596 32" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M360 80 L242 156" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M596 80 L478 156" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/></svg><figcaption><span class="fignum">Figure 2.</span> The destination by address. The destination follows from the address alone; only then is the provider found there checked.</figcaption></figure>
<p>The rule, from the reviews (Sol B1, Astra F1): the destination never depends on what is registered when the type names an
address. A request placed here whose provider is missing is <strong>unbound here</strong>, waiting for the name. A version check
@ -1358,7 +1359,7 @@ does is needed to recover; and an ended holder leaves nothing behind in any inde
<tr>
<td>2</td>
<td><code>self.get(Catalog)</code> from W1&#39;s <code>ForwardStore</code>; the parent link is up, S has published, <code>Catalog</code> is served there.</td>
<td>The request goes over the parent (placement <code>Server()</code>); S binds the hold; <code>bound</code> arrives; <code>ForwardStore</code> was <code>loading</code>, now goes on and live.</td>
<td>The request goes over the parent (<code>hostAddress: () =&gt; Server()</code>); S binds the hold; <code>bound</code> arrives; <code>ForwardStore</code> was <code>loading</code>, now goes on and live.</td>
<td>The same, after S&#39;s whole barrier (<code>Hold.start</code> awaits <code>pendingLoad</code>).</td>
<td>§1, §2</td>
</tr>