c++c++-actor-framework

What will happen to response if the sender actor is already gone?


Consider the following example. A hello_world actor sends a "hello" string to mirror actor, then it terminates immediately. What will happen to the response world returned from mirror actor? Ignored? Left in hello_world actor mailbox? Could the mirror know its response is lost?

behavior mirror(event_based_actor* self)
{
    return { [=](std::string s){ return "world"; } };
}
void hello_world(event_based_actor* self, const actor& theMirror)
{
    self->send(theMirror, "hello");
}

Solution

  • Consider the following example. A hello_world actor sends a "hello" string to mirror actor, then it terminates immediately. What will happen to the response world returned from mirror actor? Ignored? Left in hello_world actor mailbox?

    Assume that hello_world has already terminated. When the CAF runtime transfers control into mirror for the next time, the statement return "world" would attempt to send a reply to the sender. Since the sender no longer exists, the runtime simply discards the message.

    Could the mirror know its response is lost?

    TL;DR: you have to implement your own acknowledgement protocol on top if you need message delivery guarantees.

    Long answer: by monitoring an actor, you can hook its termination. Ultimately this just enqueues a specific system message in the monitoring actor's mailbox. Assuming a single-hop scenario where no message-reordering can take place, hello_world will send a message, terminate, and then the runtime will send a DOWN message to all actors that monitored hello_world. mirror's mailbox then contains first the string and then the DOWN message. This means mirror can only detect a failure after it attempted to send the message.

    There is one exception: if you spawn mirror as a priority-aware actor, it can process messages based on their priority. Think about it as two separate mailboxes per actor. All system messages in CAF have high priority, which means that there exists a scenario where you might be able to detect failure before replying, but only when the runtime transfers control into mirror after both messages already exist in mirror's mailbox. If the DOWN message gets delayed and the runtime transfers control into mirror with just the string message sitting in the mailbox, then you mirror can't detect failure either.

    That said, actors can fail at any time and the runtime can only provide near-real time fault propagation. Therefore, your design must be resilient to such failure, which means you must roll your own acknowledgement mechanism for reliable message delivery.