rustrust-actix

Why does `do_send` method not get handled in `actix` where a `send` is?


Mostly interested in what am I missing in my actix mental model, thank you in advance! Here is a pretty rudimentary actix example with ping pong messages and corresponding responses:

#[derive(Message)]
#[rtype(result = "Responses")]
enum Messages {Ping,Pong}

#[derive(Debug)]
enum Responses {GotPing,GotPong}

impl<A, M> MessageResponse<A, M> for Responses
where
    A: Actor,
    M: Message<Result = Responses>
{
    fn handle(self, _ctx: &mut A::Context, tx: Option<OneshotSender<M::Result>>) {
        if let Some(tx) = tx {tx.send(self);}
    }
}

And here is main:

#[actix_rt::main]
pub async fn main() {
    let addr           = ActorQuox.start();
    let pongfut_async  = addr.send(Messages::Pong).await;
    pongfut_async.map_or(Responses::GotPong, |res| {
        println!("Got result: {:?}", res);
        res
    });

    let ping  = addr.do_send(Messages::Ping);
}

Whereas i would expect the output to be:

Got message
Got result: GotPong
Got message

It is actually:

Got message
Got result: GotPong

I'm not sure how to reason about this given that i think that the handler impl Handler<Messages> for ActorQuox i supposed to fire on all three of do_send, send and try_send given that they all do tx.send(self) in their implementations on Addr and the difference is only in the return signatures. I'm obviously wrong about this or something else.


Solution

  • Because you can't .await a do_send(), the execution continues and will exit main(). This will cause the async runtime created by #[actix_rt::main] to shut down and will not complete any pending tasks.

    You can add a sleep() call and you'd probably see it.