core: review fixes, init builds the agent, console without a terminal
Activation path (review T6R): a broken plugin or a stray file in /plugins blocks no activation; candidates replace their own entries; discovery has a 10 s deadline and its process is stopped after the answer; an unchanged hash keeps plugin.prev.wasm; activations run in their own task; the watcher is not recursive; no duplicate services; rpc.retired waits for live processes of its version; reads and hashes on blocking threads. Guest I/O and per-call paths: a stdin write error is EOF, stdout and stderr are drained before the status; stderr is lossy UTF-8 and goes to the journal from its own reader; compiled components are freed; shutdown starts no new processes; lock queues drop stopping processes; compile before the admission gate; CommandPre per component; core.unlock in order; null errors are successes; the journal thread survives SQLite errors. sausage init builds the agent with cargo.build; sausage without a command creates ./world. The console reads plain lines without a terminal. PROTOCOL.md and DECISIONS.md describe the decided rules. The flake tests the whole workspace and checks the packaged cargo.build.
This commit is contained in:
+22
-9
@@ -138,7 +138,8 @@ Rules:
|
||||
children stop in parallel, so a whole tree takes 5 seconds at most.
|
||||
- A detached process has no parent. Only `core.stop`, `core.kill`, an
|
||||
upgrade (section 3.7), and the end of the host stop it.
|
||||
- At host shutdown, the core stops every process in parallel.
|
||||
- At host shutdown, the core starts no new processes, and it stops every
|
||||
process in parallel.
|
||||
|
||||
Note: on Unix, children outlive their parent. Here, an attached child ends
|
||||
with its parent. Only `detach` makes a process independent.
|
||||
@@ -163,6 +164,11 @@ active (section 10.3):
|
||||
During the grace period, an old process can call a method that a new
|
||||
provider no longer has.
|
||||
|
||||
If the host stops before the last old process has ended, `rpc.retired` does
|
||||
not run for that version. So a new version must also work with state that
|
||||
was not migrated. Check for a migration marker, and migrate when it is
|
||||
missing.
|
||||
|
||||
### 3.8 Environment and network
|
||||
|
||||
- `SAUSAGE_PID`: the process ID.
|
||||
@@ -325,8 +331,8 @@ are JSON Schema Draft 7, as OpenRPC requires. Shared schemas are in
|
||||
`components.schemas`, and `$ref`s point to `#/components/schemas/<Name>`.
|
||||
Params are by name. The document can have these extension fields:
|
||||
|
||||
- `x-sausage-params` for each method: a `$ref` to the schema of the params
|
||||
object.
|
||||
- `x-sausage-params` for each method with params: a `$ref` to the schema of
|
||||
the params object.
|
||||
- `x-sausage-endpoints`: the endpoint interfaces by name, each with its
|
||||
`methods`.
|
||||
- `x-sausage-imports`: for each provider, the part of its document that the
|
||||
@@ -337,8 +343,9 @@ The schema of params describes what the provider can read. The schema of a
|
||||
result describes what the provider writes. Descriptions are part of the
|
||||
interface: other agents read them to use it.
|
||||
|
||||
The core starts a process only to call `rpc.discover`. Do not do expensive
|
||||
work at start.
|
||||
The core starts a process only to call `rpc.discover`, and it stops that
|
||||
process after the answer. Do not do expensive work at start. If no answer
|
||||
comes within 10 seconds, the discovery fails.
|
||||
|
||||
### 10.2 Compatibility
|
||||
|
||||
@@ -366,11 +373,14 @@ imported method:
|
||||
1. The core copies the file. All further steps use this copy, even if the
|
||||
file changes.
|
||||
2. It starts the copy and calls `rpc.discover`.
|
||||
3. It waits until it has the documents of all plugins (section 10.4).
|
||||
3. It gets the current documents of all plugins (section 10.4). A plugin
|
||||
whose discovery fails is "unavailable". Its imports cannot be checked,
|
||||
but it does not block the activation of other plugins.
|
||||
4. It checks the imports of the new version against the current providers.
|
||||
5. It checks each current consumer of the plugin against the new version.
|
||||
6. If all checks pass, `plugin.wasm` becomes `plugin.prev.wasm`, and the copy
|
||||
becomes `plugin.wasm`. Then the upgrade starts (section 3.7).
|
||||
becomes `plugin.wasm`. Then the upgrade starts (section 3.7). If the copy
|
||||
has the same hash as the current version, nothing changes.
|
||||
|
||||
If a check fails, nothing changes, and the error -32003 lists each problem,
|
||||
with a counterexample where possible.
|
||||
@@ -391,7 +401,8 @@ with a counterexample where possible.
|
||||
- A file watcher on `/plugins/*/plugin.wasm` updates them, for example after
|
||||
a copy by hand. `/proc/core/graph.json` then shows each broken import, and
|
||||
the journal records it.
|
||||
- An import of a plugin that does not exist is "missing".
|
||||
- An import of a plugin that does not exist is "missing". An import of a
|
||||
plugin whose discovery failed is "unavailable".
|
||||
|
||||
## 11. Building and tests
|
||||
|
||||
@@ -420,6 +431,8 @@ Tests:
|
||||
and `--ignored`. `#[should_panic]` cannot work, because WASI cannot catch
|
||||
a panic.
|
||||
- Each test gets an empty temporary world as `/`, the package folder at its
|
||||
path, and its own `/proc`, `/self`, and `/run`.
|
||||
host path, and its own `/proc`, `/self`, and `/run`.
|
||||
- The current folder of a test is `/`, not the package folder. Read fixture
|
||||
files through `env!("CARGO_MANIFEST_DIR")`.
|
||||
- The test runner answers `core.lock`, `core.unlock`, `core.notify`, and
|
||||
`core.log`. A call to a plugin fails: a test has no other plugins.
|
||||
|
||||
Reference in New Issue
Block a user