80 lines
4.9 KiB
Markdown
80 lines
4.9 KiB
Markdown
---
|
|
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
|