Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Akka: communicating back outside the actor system?

Tags:

java

akka

actor

I have the following driver/main class encapsulating my Akka program:

// Groovy pseudo-code
class FizzBuzz {
    ActorSystem actorSystem

    static void main(String[] args) {
        FizzBuzz d = new FizzBuzz()
        d.run()
    }

    void run() {
        Initialize initCmd = new Initialize()
        MasterActor master = actorSystem.get(...)

        // Tells the entire actor system to initialize itself and start doing stuff.
        // ChickenCluckDetector is an actor managed/supervised by MasterActor.
        master.tell(initCmd, ...)
    }

    // Called when a ChickenCluckDetector actor inside the actor system receives
    // a 'Cluck' message.
    void onChickenGoesCluck(Cluck cluck) {
        // Do something
    }
}

And the following ChickenCluckDetector actor:

class ChickenCluckDetector extends UntypedActor {
    @Override
    void onReceive(Object message) {
        if(message instanceof Cluck) {
            Cluck cluck = message as Cluck

            // Now, how to pass the message safely/properly to FizzBuzz#onCluck?
        }
    }
}

So the problem at hand is how to safely/properly pass the Cluck message to FizzBuzz#onCluck(Cluck), which lives outside the actor system? I could provide a FizzBuzz reference to ChickenCluckDetector like so:

class ChickenCluckDetector extends UntypedActor {
    FizzBuzz fizzBuzz

    @Override
    void onReceive(Object message) {
        if(message instanceof Cluck) {
            Cluck cluck = message as Cluck

            fizzBuzz.onCluck(cluck)
        }
    }
}

But I have a feeling this violates Akka's best practices and could cause all sort of concurrency-based problems, especially if there's only one FizzBuzz (which there is) non-actor/driver, and ten thousand ChickenCluckDetector actors. Ideas?

like image 650
smeeb Avatar asked Apr 23 '15 15:04

smeeb


1 Answers

if there's only one FizzBuzz (which there is) non-actor/driver, and ten thousand ChickenCluckDetector actors

Then it would be best to create one common parent for all of these ChickenCluckDetectors. This parent could then safely hold the reference to FizzBuzz, receive clucks from all his children and call the onCluck method.

One option for getting messages outside of actors is asking. And in Scala there is actor DSL (added just for completeness). But I believe you need neither of these in your example.

public class ChickenCluckMaster extends UntypedActor {

    private FizzBuzz fizzBuzz;

    public ChickenCluckMaster(FizzBuzz fizzBuzz) {
        this.fizzBuzz = fizzBuzz;
    }

    public void onReceive(Object message) throws Exception {
        if (message instanceOf CreateDetector) {
            getContext().actorOf(
                Props.create(ChickenCluckDetector.class, getSelf); // Create child
        } else if (message instanceof Cluck) {
            fizzBuzz.onCluck(cluck);
        } else {
            unhandled(message);
        }
    }

}

public class ChickenCluckDetector extends UntypedActor {

    private ActorRef master;

    public ChickenCluckDetector(ActorRef master) {
        this.master = master;
    }

    public void onReceive(Object message) throws Exception { 
        if (message instanceof Cluck) {
            Cluck cluck = (Cluck) message;
            master.tell(cluck, getSelf);
        } else {
            unhandled(message);
        }
    }

}
like image 159
Quizzie Avatar answered Nov 11 '22 00:11

Quizzie