sausage-plugin part 2: import! with typed clients (sausage_interface::client_rs), TCP endpoints with rpc.endpoint, examples

Part 1 fixes: complete stdout writes, buffered stdin, Rust type names
in schemas, enum variant docs, -32603 for serde errors in handlers,
crate docs and modules. End-to-end check of a generated consumer through
a fake core.
This commit is contained in:
2026-10-23 00:35:45 +01:00
parent ae1cb4cc99
commit 8d3c163992
42 changed files with 3020 additions and 856 deletions
+65
View File
@@ -0,0 +1,65 @@
//! Advisory lock acquisition and guard lifetime.
use super::*;
/// An advisory lock acquisition.
pub struct Lock {
path: String,
wait: bool,
}
/// Acquire an advisory lock on a path.
pub fn lock(path: impl AsRef<Path>) -> Lock {
Lock {
path: path.as_ref().to_string_lossy().into_owned(),
wait: true,
}
}
impl Lock {
/// Return immediately, without waiting for a held lock.
pub fn try_now(mut self) -> Self {
self.wait = false;
self
}
}
/// Releases its lock on drop, unless kept until process exit.
pub struct Guard {
path: Option<String>,
}
impl Guard {
/// Hold this lock until process exit.
pub fn keep(mut self) {
self.path.take();
}
/// Report whether this guard holds the lock.
pub fn held(&self) -> bool {
self.path.is_some()
}
}
impl Drop for Guard {
fn drop(&mut self) {
if let Some(path) = self.path.take() {
let _ = notify("core.unlock", json!({"path":path}));
}
}
}
impl IntoFuture for Lock {
type Output = Result<Guard>;
type IntoFuture = LocalBoxFuture<'static, Self::Output>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move {
let lease = std::rc::Rc::new(Lease {
path: self.path.clone(),
held: std::cell::Cell::new(false),
});
let mut c = call("core.lock", json!({"path":self.path,"wait":self.wait}));
c.unlock = Some(lease.clone());
let result = c.await?;
lease.held.set(false);
Ok(Guard {
path: if result["held"] == true {
Some(self.path)
} else {
None
},
})
})
}
}