Hello guys, I am trying to learn actix, and I want to await
for a message sent to another actor inside the handle
function of another message. However, I got this error. Do you know how to fix this?
Thank you!
Hello guys, I am trying to learn actix, and I want to await
for a message sent to another actor inside the handle
function of another message. However, I got this error. Do you know how to fix this?
Thank you!
Probably you should wrap async
block with Box::pin
.
There is another issue with your code. You pass self
to a future that will be executed at some point. Rust won't allow for this. The future is passed to an executor and may be executed when self
doesn't exist any more. send_option()
can be converted to pure function or static method. This way you get rid of async
block's dependency to self
.
The Box::pin
and self
stuff doesn't seem central to this issue. The issue is that you are not in async context. Boxing is not going to save you.
You're intended to run async code in some other way afaik, but I don't know how.
Async context is not needed in case of actor handler in Actix. The handler can return a future that will be spawned in internal executor. Here is an example of how to return a future from handler when we do not need to modify actor's internal state after a future finishes:
use actix::prelude::*;
#[derive(Message)]
#[rtype(result = "Result<(), ()>")]
struct Msg;
struct MyActor;
impl Actor for MyActor {
type Context = Context<Self>;
}
impl Handler<Msg> for MyActor {
type Result = ResponseFuture<Result<(), ()>>;
fn handle(&mut self, _: Msg, _: &mut Context<Self>) -> Self::Result {
Box::pin(async move {
// Some async computation
Ok(())
})
}
}
If you want to modify actor's state after a future is executed, you can see an example in actix codebase.
It is worth to point out that ResponseFuture
and ResponseActFuture
became more permissive when it comes to future's return type since 0.10.0-alpha, which did not become stable yet.
Hi @adaqus, I tried your suggestion, but I got this new error.
My handler:
impl Handler<PlayerOption> for Player {
type Result = ResponseFuture<bool>;
fn handle(&mut self, msg: PlayerOption, _: &mut Context<Self>) -> Self::Result {
let (valid, option) = self.convert_option(msg);
let addr = self.game_addr.clone();
Box::pin(async move {
if valid {
addr.send(option).await.unwrap()
} else {
false
}
})
}
}
MessageResponse
is implemented only for ResponseFuture<Result<I, E>>
while your Result type is ResponseFuture<I>
(ResponseFuture<bool>
, to be precise). In order to make compiler accept your result type, you have to upgrade actix in your Cargo.toml to 0.10.0-alpha.3
.
It's compiled. Thank you very much. I will continue to see whether it works
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.