use rutis::{BoxFuture, CordisError, Ctx, Effect, FiberState, FiberView, Plugin, TypeKey};
struct Greeting(String);
struct Greeter {
version: u32,
}
impl Plugin for Greeter {
fn name(&self) -> &str {
"greeter"
}
fn apply<'a>(&'a self, ctx: &'a Ctx) -> BoxFuture<'a, Result<Effect, CordisError>> {
let greeting = Greeting(format!("hello from greeter v{}", self.version));
Box::pin(async move {
ctx.provide(greeting)?;
Ok(Effect::Done)
})
}
}
struct Listener {
deps: Vec<TypeKey>,
}
impl Plugin for Listener {
fn name(&self) -> &str {
"listener"
}
fn injects(&self) -> &[TypeKey] {
&self.deps }
fn apply<'a>(&'a self, ctx: &'a Ctx) -> BoxFuture<'a, Result<Effect, CordisError>> {
Box::pin(async move {
let greeting = ctx.require::<Greeting>()?.0.clone();
println!("[listener] loaded: {greeting}");
Ok(Effect::Done)
})
}
}
async fn wait_active(view: &FiberView) {
let mut rx = view.watch();
loop {
if matches!(rx.borrow().state, FiberState::Active) {
return;
}
rx.changed().await.expect("fiber driver alive");
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ctx = Ctx::root()?;
let listener = ctx.plugin(Listener {
deps: vec![TypeKey::of::<Greeting>()],
});
let v1 = ctx.plugin(Greeter { version: 1 });
wait_active(&listener).await;
v1.dispose().await?;
let _v2 = ctx.plugin(Greeter { version: 2 });
wait_active(&listener).await;
println!("done: consumer reloaded without touching it");
Ok(())
}