1use rutis::{BoxFuture, CordisError, Ctx, Effect, FiberState, FiberView, Plugin, TypeKey};
16
17struct Greeting(String);
19
20struct Greeter {
22 version: u32,
23}
24
25impl Plugin for Greeter {
26 fn name(&self) -> &str {
27 "greeter"
28 }
29 fn apply<'a>(&'a self, ctx: &'a Ctx) -> BoxFuture<'a, Result<Effect, CordisError>> {
30 let greeting = Greeting(format!("hello from greeter v{}", self.version));
31 Box::pin(async move {
32 ctx.provide(greeting)?;
33 Ok(Effect::Done)
34 })
35 }
36}
37
38struct Listener {
40 deps: Vec<TypeKey>,
41}
42
43impl Plugin for Listener {
44 fn name(&self) -> &str {
45 "listener"
46 }
47 fn injects(&self) -> &[TypeKey] {
48 &self.deps }
50 fn apply<'a>(&'a self, ctx: &'a Ctx) -> BoxFuture<'a, Result<Effect, CordisError>> {
51 Box::pin(async move {
52 let greeting = ctx.require::<Greeting>()?.0.clone();
53 println!("[listener] loaded: {greeting}");
54 Ok(Effect::Done)
55 })
56 }
57}
58
59async fn wait_active(view: &FiberView) {
62 let mut rx = view.watch();
63 loop {
64 if matches!(rx.borrow().state, FiberState::Active) {
65 return;
66 }
67 rx.changed().await.expect("fiber driver alive");
68 }
69}
70
71#[tokio::main]
72async fn main() -> Result<(), Box<dyn std::error::Error>> {
73 let ctx = Ctx::root()?;
74
75 let listener = ctx.plugin(Listener {
77 deps: vec![TypeKey::of::<Greeting>()],
78 });
79
80 let v1 = ctx.plugin(Greeter { version: 1 });
82 wait_active(&listener).await; v1.dispose().await?;
88 let _v2 = ctx.plugin(Greeter { version: 2 });
89 wait_active(&listener).await;
90 println!("done: consumer reloaded without touching it");
91 Ok(())
92}