Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Actor processing messages at the same time #4

Open
sezaru opened this issue Jul 10, 2022 · 2 comments
Open

[BUG] Actor processing messages at the same time #4

sezaru opened this issue Jul 10, 2022 · 2 comments

Comments

@sezaru
Copy link

sezaru commented Jul 10, 2022

In my testing, it seems like an actor is actually handling multiple messages at the same time. This seems like an unexpected behavior for me, I was expecting that the actor would only process one message at a time and only pick another one when that first one is done.

Note that my background is with Erlang's actor model, not Akka, so I'm not sure if this is handled differently in Akka.

Update: I just looked at Akka documentation and their actors process data sequentially too:

The second key change we need in our model is to reinstate encapsulation. Actors react to messages just like objects “react” to methods invoked on them. The difference is that instead of multiple threads “protruding” into our actor and wreaking havoc to internal state and invariants, actors execute independently from the senders of a message, and they react to incoming messages sequentially, one at a time. While each actor processes messages sent to it sequentially, different actors work concurrently with each other so that an actor system can process as many messages simultaneously as the hardware will support.

Here is an example code to test it:

class TestActor extends UntypedActor {
  int state = 0;

  @override
  void onStart(UntypedActorContext context) {
    print('starting ${context.path}');

    context.receive<int>((message) async {
      await Future.delayed(Duration(milliseconds: (Random().nextInt(10) * 100)));

      print('got int message: ${message}, current_state: ${state}');

      state = message;

      return;
    });
  }
}

void main() {
  var system = ActorSystem('test_system');

  await system.initialize();
  await system.actorOf('test_actor', TestActor());

  final ref = system.getLocalActorRef('../test_actor');

  ref?.send(1);
  ref?.send(2);
  ref?.send(3);
}

So, as you can see, the receive handler will wait some random time per message, then print the message and state and finally update the state.

If the messages were being handled one-by-one, the output should be deterministic and the app should print this:

got int message: 1, current_state: 0
got int message: 2, current_state: 1
got int message: 3, current_state: 2

But instead, I'm getting this:

got int message: 1, current_state: 0
got int message: 3, current_state: 1
hot int message: 2, current_state: 3
@GlebBatykov
Copy link
Owner

GlebBatykov commented Jul 10, 2022

Hi!

You've touched a very good topic for discussion. During the development of the library, I was constantly thinking about how actors should handle incoming messages. Asynchronously or sequentially?

I've been thinking about it a lot.

In general, until recently (and now in the version that is uploaded to pub.dev), messages are processed asynchronously.

But at the moment, I was working on providing the ability to configure this. So the actors could process the messages coming to them both sequentially and asynchronously.

The release of a new version of the library where I add this functionality has been delayed, due to some of my reasons. But, if someone is interested in this library, I will try to release a new update with this functionality as soon as possible.

@sezaru
Copy link
Author

sezaru commented Jul 10, 2022

Yeah, having the ability to make it sequential would be awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants