Skip to content

Not possible to use ask-pattern from inside recv function of an actor #164

@Superhepper

Description

@Superhepper

I wonder if it is possible to use the ask pattern from inside recv function in actor to make a blocking call to another actor in the same system. Because when I try to do that I always get an error regarding LocalPool.

I have made a very simple example (see code below) where I try to use the ask-pattern from inside another actors recv function. But this only results in the following error:

thread 'pool-thread-#3' panicked at 'cannot execute `LocalPool` executor from within another executor: EnterError', ~/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-0.3.14/src/local_pool.rs:78:26

main.rs

mod ask;
mod reply;

use ask::{AskActor, AskActorMsg, PrintNewSentenceRequest};
use reply::ReplyActor;

use riker::actors::*;

fn main() {
    let sys = ActorSystem::new().unwrap();

    let reply_actor = sys
        .actor_of_args::<ReplyActor, _>("ReplyActor", "new".to_string())
        .unwrap();
    let ask_actor = sys
        .actor_of_args::<AskActor, _>("AskActor", reply_actor)
        .unwrap();

    ask_actor.tell(
        AskActorMsg::PrintNewSentenceRequest(PrintNewSentenceRequest {}),
        None,
    );

    std::thread::sleep(std::time::Duration::from_millis(500));
}

ask.rs

use crate::reply::{PrefixRequest, PrefixResponse, ReplyActorMsg};
use futures::executor::block_on;
use futures::future::RemoteHandle;
use riker::actors::*;
use riker_patterns::ask::*;

#[derive(Debug, Clone)]
pub struct PrintNewSentenceRequest {}

#[actor(PrintNewSentenceRequest)]
#[derive(Debug, Clone)]
pub struct AskActor {
    reply_actor: ActorRef<ReplyActorMsg>,
}

impl ActorFactoryArgs<ActorRef<ReplyActorMsg>> for AskActor {
    fn create_args(reply_actor: ActorRef<ReplyActorMsg>) -> Self {
        AskActor { reply_actor }
    }
}

impl Actor for AskActor {
    type Msg = AskActorMsg;

    fn recv(&mut self, ctx: &Context<Self::Msg>, msg: Self::Msg, sender: Sender) {
        self.receive(ctx, msg, sender)
    }
}

impl Receive<PrintNewSentenceRequest> for AskActor {
    type Msg = AskActorMsg;

    fn receive(&mut self, ctx: &Context<Self::Msg>, _: PrintNewSentenceRequest, _: Sender) {
        let r: RemoteHandle<PrefixResponse> = ask(
            &ctx.system,
            &self.reply_actor,
            ReplyActorMsg::PrefixRequest(PrefixRequest {
                word: "ball".to_string(),
            }),
        );

        let response = block_on(r);

        println!("Received new sentence: {}", response.sentence);
    }
}

reply.rs

use riker::actors::*;

#[derive(Debug, Clone)]
pub struct PrefixRequest {
    pub word: String,
}

#[derive(Debug, Clone)]
pub struct PrefixResponse {
    pub sentence: String,
}

#[actor(PrefixRequest)]
#[derive(Debug, Clone)]
pub struct ReplyActor {
    prefix: String,
}

impl ActorFactoryArgs<String> for ReplyActor {
    fn create_args(prefix: String) -> Self {
        ReplyActor { prefix }
    }
}

impl Actor for ReplyActor {
    type Msg = ReplyActorMsg;

    fn recv(&mut self, ctx: &Context<Self::Msg>, msg: Self::Msg, sender: Sender) {
        self.receive(ctx, msg, sender)
    }
}

impl Receive<PrefixRequest> for ReplyActor {
    type Msg = ReplyActorMsg;

    fn receive(&mut self, _: &Context<Self::Msg>, request: PrefixRequest, sender: Sender) {
        sender
            .as_ref()
            .clone()
            .unwrap()
            .try_tell(
                PrefixResponse {
                    sentence: format!("{} {}", self.prefix, request.word),
                },
                None,
            )
            .unwrap()
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions