elfo-rs / elfo

An asynchronous distributed actor framework in Rust with robust observability
265 stars 16 forks source link

Proxy: methods to test failed `send()` #72

Open loyd opened 2 years ago

loyd commented 2 years ago

Now send() panics if there is an error. Sometimes it's useful to check it.

sargarass commented 1 year ago

so does request().

It would be nice to have it without a built-in panic, so that in the following code, it would be possible to check for request errors.

#[tokio::test]
async fn test() {
    #[message(ret=())]
    struct Ping {
        target: u32,
    }

    #[message]
    struct Spawn {
        target: u32,
    }

    #[message]
    struct Stop {
        target: u32,
    }

    use elfo::{
        routers::{MapRouter, Outcome},
        ActorGroup, Context,
    };
    fn new() -> Blueprint {
        ActorGroup::new()
            .restart_policy(RestartPolicy::never())
            .router(MapRouter::new(|envelope| {
                msg!(match envelope {
                    Spawn { target, .. } => Outcome::Unicast(*target),
                    Ping { target } => Outcome::GentleUnicast(*target),
                    Stop { target, .. } => Outcome::GentleUnicast(*target),
                    _ => Outcome::Default,
                })
            }))
            .exec(move |ctx| async move {
                async fn run(mut ctx: Context<(), u32>) -> eyre::Result<()> {
                    info!("i'm awake", id = ctx.key());

                    while let Some(m) = ctx.recv().await {
                        msg!(match m {
                            Spawn => {}
                            Stop => break,
                            (Ping, token) => {},
                        })
                    }
                    info!("stopped", id = ctx.key());
                    Ok(())
                }

                run(ctx).await
            })
    }

    let mut test = elfo::test::proxy(new(), AnyConfig::default()).await;

    test.send(Spawn { target: 1 }).await;
    test.send(Spawn { target: 2 }).await;
    test.send(Spawn { target: 3 }).await;

    test.send(Stop { target: 2 }).await;

    tokio::time::sleep(Duration::from_secs(1)).await;

    // ignored
    test.request(Ping { target: 1}).await; //panics, would be nice to check error here
    // failed
    let test = test.request(Ping { target: 2}).await;  //panics, would be nice to check error here
}