Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c204e1ef0c | ||
|
|
6923ca3e60 | ||
|
|
c504532513 | ||
|
|
eb35a79698 | ||
|
|
bfcd71e2f4 |
+3
-1
@@ -63,10 +63,12 @@ Each instance sees three folders:
|
|||||||
|
|
||||||
| Path | Access | Contents |
|
| Path | Access | Contents |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `/data` | read-write | the actor's state |
|
| `/data` | read-write by its actor; readable by every actor | the actor's state |
|
||||||
| `/public` | read-write | the files that the actor publishes |
|
| `/public` | read-write | the files that the actor publishes |
|
||||||
| `/actor` | read-only | the `actor/` folder of the world |
|
| `/actor` | read-only | the `actor/` folder of the world |
|
||||||
|
|
||||||
|
An actor can write only its own `/data`, but can read every actor's `/data` through `/actor/<id>/data/`. `/data` is not private: any unprotected secret file there is readable by every actor.
|
||||||
|
|
||||||
`/actor/<id>/` holds everything about an actor: `actor.wasm`, `actor.json`
|
`/actor/<id>/` holds everything about an actor: `actor.wasm`, `actor.json`
|
||||||
(installed version, running, subscriptions, tapped, watches), `source/`, `public/`, `data/`,
|
(installed version, running, subscriptions, tapped, watches), `source/`, `public/`, `data/`,
|
||||||
`stderr.log`, and `versions/<n>/`. `ls /actor` lists all actors.
|
`stderr.log`, and `versions/<n>/`. `ls /actor` lists all actors.
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ actor.wasm the current version
|
|||||||
actor.json installed version, running, subscriptions
|
actor.json installed version, running, subscriptions
|
||||||
source/ the source of the current version
|
source/ the source of the current version
|
||||||
public/ files that the actor publishes
|
public/ files that the actor publishes
|
||||||
data/ the actor's state
|
data/ actor state; owner-writable, world-readable via /actor/<id>/data/ (not private)
|
||||||
stderr.log what the actor and the broker write about it
|
stderr.log what the actor and the broker write about it
|
||||||
versions/<n>/ every installed version: actor.wasm, source/, meta.json
|
versions/<n>/ every installed version: actor.wasm, source/, meta.json
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ People talk to you through other actors. Your text goes to your subscribers.
|
|||||||
Before writing an actor, read `/actor/broker/public/PROTOCOL.md` for messages, the broker, `cargo`, and tests.
|
Before writing an actor, read `/actor/broker/public/PROTOCOL.md` for messages, the broker, `cargo`, and tests.
|
||||||
Read the SDK at `/actor/cargo/public/sdk/` before you write an actor.
|
Read the SDK at `/actor/cargo/public/sdk/` before you write an actor.
|
||||||
You can change your own source at `/actor/agent/source`.
|
You can change your own source at `/actor/agent/source`.
|
||||||
|
|
||||||
|
The global filesystem is readable by every actor, including every actor's `/data` at `/actor/<id>/data/`. An actor can write only its own `/data` and `/public`. `/data` is not private: any unprotected secret file there is readable by every actor.
|
||||||
|
|||||||
@@ -21,9 +21,11 @@
|
|||||||
targets = [ "wasm32-wasip2" ];
|
targets = [ "wasm32-wasip2" ];
|
||||||
extensions = [ "rust-src" ];
|
extensions = [ "rust-src" ];
|
||||||
};
|
};
|
||||||
# Crane builds the dependencies once (`cargoArtifacts`, keyed only on
|
# The runtime cargo actor needs Cargo, rustc (with wasm32-wasip2), and
|
||||||
# Cargo.toml/Cargo.lock), so a change to our own crates rebuilds
|
# the native linker, even when the host itself is started with a bare
|
||||||
# just them.
|
# PATH. Keep this same runtime path in the packaged host and exercise
|
||||||
|
# the installed binary below with PATH deliberately empty.
|
||||||
|
runtimePath = pkgs.lib.makeBinPath [ rust pkgs.stdenv.cc ];
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain rust;
|
craneLib = (crane.mkLib pkgs).overrideToolchain rust;
|
||||||
common = {
|
common = {
|
||||||
pname = "sausage";
|
pname = "sausage";
|
||||||
@@ -42,12 +44,13 @@
|
|||||||
});
|
});
|
||||||
sausage = craneLib.buildPackage (common // {
|
sausage = craneLib.buildPackage (common // {
|
||||||
inherit cargoArtifacts;
|
inherit cargoArtifacts;
|
||||||
|
doNotRemoveReferencesToRustToolchain = true;
|
||||||
cargoExtraArgs = "--locked -p sausage";
|
cargoExtraArgs = "--locked -p sausage";
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||||
# The `cargo` actor runs cargo at runtime. Build scripts need a C linker.
|
# The `cargo` actor runs cargo at runtime. Build scripts need a C linker.
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
wrapProgram $out/bin/sausage --prefix PATH : ${pkgs.lib.makeBinPath [ rust pkgs.stdenv.cc ]}
|
wrapProgram $out/bin/sausage --prefix PATH : ${runtimePath}
|
||||||
'';
|
'';
|
||||||
meta.mainProgram = "sausage";
|
meta.mainProgram = "sausage";
|
||||||
});
|
});
|
||||||
@@ -91,6 +94,69 @@
|
|||||||
rm -f cli/tests/actors/toolbox/Cargo.lock
|
rm -f cli/tests/actors/toolbox/Cargo.lock
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
# Exercise the installed host exactly as the loop launches it: the
|
||||||
|
# caller has no Cargo on PATH, so only the packaged runtime toolchain
|
||||||
|
# can run the native tests and the wasm32-wasip2 build.
|
||||||
|
checks.runtime-toolchain = pkgs.runCommand "sausage-runtime-toolchain" { } ''
|
||||||
|
set -eu
|
||||||
|
root="$TMPDIR/runtime-toolchain"
|
||||||
|
world="$root/world"
|
||||||
|
emptyPath="$root/empty-bin"
|
||||||
|
mkdir -p "$emptyPath" "$root/home" "$root/cargo-home"
|
||||||
|
for actor in broker console cargo fs; do
|
||||||
|
mkdir -p "$world/actor/$actor/public" "$world/actor/$actor/data"
|
||||||
|
done
|
||||||
|
source="$world/actor/console/public/probe"
|
||||||
|
mkdir -p "$source/src" "$source/tests"
|
||||||
|
cat > "$source/Cargo.toml" <<'TOML'
|
||||||
|
[package]
|
||||||
|
name = "runtime-probe"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
TOML
|
||||||
|
printf 'fn main() {}\n' > "$source/src/main.rs"
|
||||||
|
cat > "$source/tests/probe.rs" <<'RUST'
|
||||||
|
#[test]
|
||||||
|
fn native_test_harness_runs() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
|
RUST
|
||||||
|
echo "runtime-check: run packaged host with an empty PATH"
|
||||||
|
coproc host {
|
||||||
|
${pkgs.coreutils}/bin/env -i PATH="$emptyPath" HOME="$root/home" TMPDIR="$root" \
|
||||||
|
CARGO_HOME="$root/cargo-home" ${sausage}/bin/sausage run "$world"
|
||||||
|
}
|
||||||
|
hostInput=''${host[1]}
|
||||||
|
hostOutput=''${host[0]}
|
||||||
|
hostPid=$host_PID
|
||||||
|
trap 'kill "$hostPid" 2>/dev/null || true' EXIT
|
||||||
|
printf '%s\n' '@cargo {"type":"build","source":"/actor/console/public/probe"}' >&"$hostInput"
|
||||||
|
built=0
|
||||||
|
while IFS= read -r -t 300 line <&"$hostOutput"; do
|
||||||
|
echo "$line"
|
||||||
|
case "$line" in
|
||||||
|
*'"type":"build_failed"'*)
|
||||||
|
echo "packaged cargo actor build failed with an empty caller PATH" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*'"type":"built"'*)
|
||||||
|
case "$line" in
|
||||||
|
*'"passed":1'*) built=1 ;;
|
||||||
|
*) echo "native test did not pass" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ "$built" -ne 1 ]; then
|
||||||
|
echo "packaged host did not build the probe" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf '%s\n' '/quit' >&"$hostInput"
|
||||||
|
wait "$hostPid"
|
||||||
|
mkdir -p "$out"
|
||||||
|
touch "$out/passed"
|
||||||
|
'';
|
||||||
|
|
||||||
apps.default = { type = "app"; program = "${sausage}/bin/sausage"; };
|
apps.default = { type = "app"; program = "${sausage}/bin/sausage"; };
|
||||||
apps.loop = { type = "app"; program = "${loop}/bin/sausage-loop"; };
|
apps.loop = { type = "app"; program = "${loop}/bin/sausage-loop"; };
|
||||||
|
|||||||
Reference in New Issue
Block a user