Host: fixes from the review, with regression tests

- one live instance per actor: check after the lock; dropping an instance kills it
- state snapshots keep target/ and .git/; only source copies skip them
- one shutdown deadline; output during shutdown is still routed
- deliveries route stdout meanwhile; a stuck stdin kills the instance
  (no partial lines) and the sender gets undeliverable; control requests
  are not blocked by a stuck delivery
- Host::stop aborts running broker and cargo requests first
- compile a version before installing it; roll back if it does not start
- unique archive names; a failed archive keeps the actor manageable
- commit on close: truncate without create; directory renames
- candidates see SAUSAGE_VERSION and the existing state of a new actor
- the host publishes PROTOCOL.md at /actor/broker/public/
This commit is contained in:
2026-10-15 12:03:26 +01:00
parent 69cf80a114
commit 9d575b6a62
11 changed files with 811 additions and 220 deletions
+10 -3
View File
@@ -1,7 +1,8 @@
# The Sausage protocol
This document is the contract between the host and the actors. An actor in
any language that follows it works in Sausage.
any language that follows it works in Sausage. The host publishes this file at
`/actor/broker/public/PROTOCOL.md`, so every actor can read it.
## Actors
@@ -43,10 +44,14 @@ A line on **stdout**:
mailbox keeps messages while the actor restarts or is upgraded.
- If the broker cannot deliver a message, the sender gets
`{"type": "undeliverable", "reason": "...", "to": "..."}` from `broker`.
- An actor must keep reading stdin. If a message waits 30 seconds for the
actor to read it, the broker kills and restarts the actor, and the sender
gets `undeliverable`.
Before the broker stops an instance, it sends
`{"id": "broker/shutdown", "from": "broker", "body": {"type": "shutdown"}}`
and then closes stdin. After 5 seconds, it kills the instance.
and then closes stdin. The broker still routes what the actor writes until
it exits. After 5 seconds, it kills the instance.
## Filesystem
@@ -93,7 +98,9 @@ sender's).
has `"rejected"` in its `meta.json`.
**Tests.** Before a spawn or an upgrade, the broker runs the candidate on a
copy of the actor's `/data` and `/public`, without HTTP. The tests are JSON
copy of the actor's `/data` and `/public` (empty for a new actor), without
HTTP. The candidate sees its future `SAUSAGE_VERSION` and
`SAUSAGE_CANDIDATE=1`. The tests are JSON
files in `source/tests/*.json`:
```json