core: sausage-vfs per process (/, /proc, /self, /run), activation, graph, watcher, upgrades

- /proc is a core layer: core/ (PROTOCOL.md, graph.json, graph.dot,
  locks.json, plugins/<name>/discover.json and client.rs) and one folder
  per process (info.json, log, and its /self files).
- Locks are released only after the task ended, the store dropped, and
  in-flight file operations returned.
- core.activate and core.revert with copies, discovery, compatibility
  checks of imports and consumers, groups, force. An admission gate
  makes the snapshot of old processes complete.
- Graph of discover documents by hash, refreshed by a file watcher.
- Upgrades: grace periods (x-sausage-grace), stop, service restarts,
  rpc.retired.
- SDK plugins in the real core (cli/tests/sdk.rs).
This commit is contained in:
2026-10-23 01:05:19 +01:00
parent 151550242b
commit edc2d1a63b
21 changed files with 2306 additions and 101 deletions
+11 -10
View File
@@ -1,7 +1,7 @@
//! Execution of native futures and WASI processes, including transport drainage.
use crate::{
Host, NativeContext, NativePlugin,
process::{ProcessGuard, ProcessInfo},
process::ProcessInfo,
runtime::{Instance, InstanceConfig},
};
use serde_json::{Value, json};
@@ -17,11 +17,7 @@ impl Host {
native: Option<NativePlugin>,
incoming: mpsc::UnboundedReceiver<Value>,
has_id: bool,
) {
let _guard = ProcessGuard {
host: self.clone(),
pid: pid.clone(),
};
) -> String {
if let Some(native) = native {
let context = NativeContext {
host: self.clone(),
@@ -29,13 +25,12 @@ impl Host {
};
let result = native(context, info.method, info.params).await;
self.answer(&pid, result);
self.finish(&pid, "exit 0");
return;
return "exit 0".into();
}
let result = self
.run_guest(&pid, &info, &component.unwrap(), incoming, has_id)
.await;
self.finish(&pid, &result.unwrap_or_else(|error| error.to_string()));
result.unwrap_or_else(|error| error.to_string())
}
/// Drain stdout before deciding whether the guest returned an answer.
@@ -47,8 +42,14 @@ impl Host {
mut incoming: mpsc::UnboundedReceiver<Value>,
has_id: bool,
) -> anyhow::Result<String> {
let (memory, tracker, store_ended) = {
let state = self.0.state.lock().unwrap();
let p = state.processes.get(pid).unwrap();
(p.memory.clone(), p.files.clone(), p.store_ended.clone())
};
let config = InstanceConfig {
world: self.0.world.root.clone(),
filesystem: self.mounts(Some(pid.into()), memory, tracker).await?,
store_ended,
network: true,
env: vec![
("SAUSAGE_PID".into(), pid.into()),