Add armed plugin-originated file watches across VFS mutations
Register core.watch before its armed notification, coalesce later changes without losing post-notification writes, and clean up on caller death. Observe mounted layers and open file handles, including descriptor/stream writes, truncation, both rename paths and deletion. Track cancelled mutations through process idle and retain visible paths across renames. Document the protocol, expose native core discovery, and exercise watches through SDK callbacks and raw WASI filesystem operations. Card: SAU-359
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
use sausage_plugin::serde_json::{Value, json};
|
||||
use sausage_plugin::{Ctx, Result, call, lock, rpc, schema};
|
||||
struct Probe;
|
||||
/// A virtual path to observe.
|
||||
#[schema]
|
||||
struct WatchPath {
|
||||
/// Directory or file, not necessarily present yet.
|
||||
path: String,
|
||||
}
|
||||
/// The values to add.
|
||||
#[schema]
|
||||
struct Add {
|
||||
@@ -30,6 +36,33 @@ struct Echo {
|
||||
}
|
||||
#[rpc(grace_seconds = 12,endpoints(control=Control))]
|
||||
impl Probe {
|
||||
/// Scan only after the watch is armed; keep the call open until process death.
|
||||
async fn watch(&self, p: WatchPath) -> Result<()> {
|
||||
let path = p.path.clone();
|
||||
call("core.watch", json!({"path":p.path}))
|
||||
.on_notify(move |name, _| {
|
||||
if name == "armed" && path == "/self" {
|
||||
std::fs::write("/self/owned", "visible via proc").unwrap();
|
||||
}
|
||||
let mut entries: Vec<_> = std::fs::read_dir(&path)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(std::result::Result::ok)
|
||||
.map(|e| e.file_name().into_string().unwrap())
|
||||
.collect();
|
||||
entries.sort();
|
||||
let text = std::fs::read_to_string(format!("{path}/before")).ok();
|
||||
Ctx::default()
|
||||
.notify(
|
||||
name,
|
||||
json!({"pid":sausage_plugin::pid(), "entries":entries, "text":text}),
|
||||
)
|
||||
.unwrap();
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Publish a control endpoint until EOF.
|
||||
async fn serve(&self) -> Result<()> {
|
||||
sausage_plugin::listen("/endpoint", std::rc::Rc::new(Control)).await
|
||||
|
||||
Reference in New Issue
Block a user