sausage-plugin part 1: run, #[rpc], #[schema], rpc.discover, calls, locks, Ctx, hooks
Checkpoint. Known issues, fixed in part 2: short writes on stdout, byte-wise stdin reads, Result suffix on all result schemas, lost enum variant docs, serde errors as invalid params, missing item docs.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
//! Probe of SDK transport and lifecycle behavior.
|
||||
use sausage_plugin::serde_json::{Value, json};
|
||||
use sausage_plugin::{Ctx, Result, call, lock, rpc, schema};
|
||||
struct Probe;
|
||||
/// The values to add.
|
||||
#[schema]
|
||||
struct Add {
|
||||
/// The first number.
|
||||
a: i32,
|
||||
/// The second number.
|
||||
b: i32,
|
||||
}
|
||||
/// The retired version.
|
||||
#[schema]
|
||||
struct Retired {
|
||||
/// The previous hash.
|
||||
previous: String,
|
||||
}
|
||||
#[rpc(grace_seconds = 12)]
|
||||
impl Probe {
|
||||
/// Add two numbers.
|
||||
///
|
||||
/// The result is their sum.
|
||||
fn add(&self, p: Add) -> Result<i32> {
|
||||
Ok(p.a + p.b)
|
||||
}
|
||||
/// Return a deliberate error.
|
||||
fn fail(&self) -> Result<String> {
|
||||
Err(sausage_plugin::Error::new(-32010, "deliberate"))
|
||||
}
|
||||
/// Exercise calls, notifications, and advisory locks.
|
||||
async fn exercise(&self, ctx: &Ctx) -> Result<String> {
|
||||
let a =
|
||||
call("other.first", json!({})).on_notify(|name, _| eprintln!("notification: {name}"));
|
||||
let b = call("other.second", json!({})).detach();
|
||||
let (a, b) = join(a, b).await;
|
||||
a?;
|
||||
b?;
|
||||
ctx.notify("progress", json!({"done":true}))?;
|
||||
{
|
||||
let guard = lock("/state/probe/file").await?;
|
||||
assert!(guard.held());
|
||||
}
|
||||
assert!(!lock("/state/probe/file").try_now().await?.held());
|
||||
Ok("done".into())
|
||||
}
|
||||
/// Drop an acquisition before the core grants its lock.
|
||||
async fn late(&self) -> Result<String> {
|
||||
{
|
||||
let mut future = std::pin::pin!(std::future::IntoFuture::into_future(lock("/late")));
|
||||
std::future::poll_fn(|cx| {
|
||||
assert!(future.as_mut().poll(cx).is_pending());
|
||||
std::task::Poll::Ready(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
call("other.barrier", json!({})).await?;
|
||||
lock("/kept").await?.keep();
|
||||
Ok("late done".into())
|
||||
}
|
||||
/// Mark a retired version.
|
||||
#[sausage_plugin::on_retired]
|
||||
fn retired(&self, p: Retired) -> Result<String> {
|
||||
Ok(p.previous)
|
||||
}
|
||||
/// Wait until EOF, then run the stop hook.
|
||||
async fn wait(&self) -> Result<String> {
|
||||
call("other.wait", json!({})).await?;
|
||||
Ok("done".into())
|
||||
}
|
||||
/// Keep the process alive with a background call.
|
||||
fn start(&self) -> Result<String> {
|
||||
sausage_plugin::background(async {
|
||||
let _ = call("other.background", json!({})).await;
|
||||
});
|
||||
Ok("started".into())
|
||||
}
|
||||
/// Save an EOF marker.
|
||||
#[sausage_plugin::on_stop]
|
||||
async fn stop(&self) {
|
||||
std::fs::write("/stopped", b"yes").unwrap();
|
||||
Ctx::default().notify("stopped", json!({})).unwrap();
|
||||
assert!(call("other.no", json!({})).await.is_err());
|
||||
}
|
||||
}
|
||||
async fn join(
|
||||
a: impl std::future::IntoFuture<Output = Result<Value>>,
|
||||
b: impl std::future::IntoFuture<Output = Result<Value>>,
|
||||
) -> (Result<Value>, Result<Value>) {
|
||||
let mut a = std::pin::pin!(a.into_future());
|
||||
let mut b = std::pin::pin!(b.into_future());
|
||||
let (mut av, mut bv) = (None, None);
|
||||
std::future::poll_fn(move |cx| {
|
||||
if av.is_none() {
|
||||
if let std::task::Poll::Ready(v) = a.as_mut().poll(cx) {
|
||||
av = Some(v);
|
||||
}
|
||||
}
|
||||
if bv.is_none() {
|
||||
if let std::task::Poll::Ready(v) = b.as_mut().poll(cx) {
|
||||
bv = Some(v);
|
||||
}
|
||||
}
|
||||
if av.is_some() && bv.is_some() {
|
||||
std::task::Poll::Ready((av.take().unwrap(), bv.take().unwrap()))
|
||||
} else {
|
||||
std::task::Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
fn main() {
|
||||
sausage_plugin::run(Probe)
|
||||
}
|
||||
Reference in New Issue
Block a user