- The serve loop ends the process after EOF or exit_after_response, also with background tasks or listeners. - One schema generator per direction for the whole document, so types with the same name get distinct names. - The agent gives the complete error (code, message, data) to the model, writes SKIP only after a successful request, caps tool output at 64 KiB, writes each history line in one write, and skips a damaged line. - Endpoints skip blank and non-RPC lines. client_rs does not panic. - #[must_use] on builders and the lock guard; #[schemars] attributes and duplicate hooks are compile errors; raw identifiers; -32000 for local SDK errors; x-sausage-params only for methods with params.
68 lines
1.8 KiB
Rust
68 lines
1.8 KiB
Rust
//! Advisory lock acquisition and guard lifetime.
|
|
use super::*;
|
|
/// An advisory lock acquisition.
|
|
#[must_use = "await the lock to acquire it"]
|
|
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.
|
|
#[must_use = "bind the guard to hold the lock"]
|
|
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
|
|
},
|
|
})
|
|
})
|
|
}
|
|
}
|