ADR 0198: a module's long-running code is launched by the node's runtime and reaches the bus through it; research 022; design 38 WP4c plan
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
||||
---
|
||||
topic: what runs on it
|
||||
status: accepted
|
||||
date: 2026-10-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md
|
||||
---
|
||||
|
||||
# 198. A module's long-running code is launched by the node's runtime, and reaches the bus through it
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0193](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md) made
|
||||
every tools bundle a child the node's runtime launches, speaking MCP over stdio, and gave the channel
|
||||
one bus verb: a tool's emit, published by the runtime as the module. Twenty-three modules still run the
|
||||
rest of their own code — event handlers, provisioners, a preparation step, three mains — in a container
|
||||
on the runtime's image, because that code needs what a container gave it: a bus connection that can
|
||||
*subscribe*, and its module's words. Research [022](../01-RESEARCH/022-where-a-modules-long-running-code-runs/00-overview.md)
|
||||
measured what it uses. [ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
||||
§1 says a module's own code is never an image.
|
||||
|
||||
## Considered Options
|
||||
|
||||
1. **The runtime launches it and is its bus.** Chosen.
|
||||
2. A process per module with its own bus client and credential. Rejected for the reasons ADR 0188
|
||||
rejected it for tools: a transport in every language's SDK, a credential per module on disk, and a
|
||||
bus change rebuilding every module.
|
||||
3. Keep the containers for it. Rejected: ADR 0188's rule stays broken for most of the catalogue.
|
||||
|
||||
## Decision
|
||||
|
||||
**1. A module's long-running code is a bundle the node's runtime launches and supervises,** exactly as
|
||||
its tools are: an executable entrypoint, given the runtime's words and its module's
|
||||
([ADR 0192](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md)),
|
||||
started at the runtime's start and again when it exits. A bundle may serve tools, run long, or both.
|
||||
|
||||
**2. The runtime is its bus.** The stdio channel carries, beside MCP, the mesh's verbs a module's code
|
||||
uses: `mesh/publish` (ADR 0193), **`mesh/subscribe`** — the runtime binds that module's durable
|
||||
consumer, as the module's own runtime did, and delivers each event to the child as a `mesh/event`
|
||||
request, acknowledging it on the bus only when the child has answered — and **`mesh/ask`**, a tool
|
||||
call made on the module's behalf. The runtime's account is granted what each module it carries
|
||||
consumes, and the consumer keeps the module's name, so no event is lost or replayed in the move.
|
||||
|
||||
**3. A preparation step is a run-once process the host runs before the runtime starts the module,**
|
||||
with its module's words and no bus — what it already was.
|
||||
|
||||
**4. What a container reached by its network is reached on the machine.** A service by its published
|
||||
port (`${port:…}`) on loopback; a backend's command-line client as a package of the machine's system,
|
||||
or, where the system has none, the backend's own driver inside the bundle.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The per-module containers go, and with them the runtime image as a way module code runs; ADR 0188's
|
||||
registration rule can then refuse a module's own image without exception.
|
||||
- One bus connection per machine carries every module's events; a module's handler is a function of
|
||||
the events it is handed, in any language, with no bus client of its own.
|
||||
- What got harder: the runtime holds every carried module's consumer and must not acknowledge an event
|
||||
before the child has handled it — a child that dies mid-event leaves it unacknowledged, and it is
|
||||
delivered again. The runtime's grants widen to what its modules consume.
|
||||
- Two modules need code before they can move: their backends' clients exist on no machine's system,
|
||||
so they talk to the backend through a driver instead.
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| A subscribed event reaches the child and is acknowledged only after it answered | the runtime's test over a real bus: a child that answers is acknowledged once; one that dies mid-event is delivered again |
|
||||
| The module's consumer keeps its name | the composer's test: the durable consumer the runtime binds is the one the module's own runtime bound |
|
||||
| No module's own code is an image | the catalogue's registration check, without exception, once the last container has moved |
|
||||
| Live | every moved module's provisioner and handlers act, on their machines, from the node's runtime; `docker ps` shows no runtime-image container on any machine |
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md),
|
||||
[ADR 0192](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md),
|
||||
[ADR 0193](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)
|
||||
- Research [022](../01-RESEARCH/022-where-a-modules-long-running-code-runs/00-overview.md)
|
||||
- [to-be 38](../03-DESIGN/01-to-be/38-building-the-operators-machine.md) WP4c
|
||||
@@ -297,6 +297,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0193** — [Every bundle the runtime serves is launched, and the runtime knows no language](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)
|
||||
- **0195** — [The mesh's tools are found by address, not announced whole](0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)
|
||||
- **0197** — [Every tool announces itself on the bus, in the NATS services protocol](0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md)
|
||||
- **0198** — [A module's long-running code is launched by the node's runtime, and reaches the bus through it](0198-a-modules-long-running-code-is-launched-by-the-node-runtime-and-reaches-the-bus-through-it.md)
|
||||
|
||||
### How it is built
|
||||
|
||||
|
||||
Reference in New Issue
Block a user