riker-rs / riker

Easily build efficient, highly concurrent and resilient applications. An Actor Framework for Rust.
https://riker.rs
MIT License
1.03k stars 69 forks source link

why only one system per application? #17

Closed thedavidmeister closed 5 years ago

thedavidmeister commented 6 years ago

i saw this in the docs but wasn't sure why

it seems like it would be advantageous to have an actor system in a module with its own protocol

what are the consequences of having more than one system running?

leenozara commented 6 years ago

Using multiple actor systems in a single application can take some coordinating, especially with configuration. This is especially true when you're using any kind of persistence that is local, i.e. file based. You'll potentially get two systems conflicting over the local persistence. This is also for any socket bindings you might perform. You're also going to get multiple schedulers which would

ActorSystem::new is fairly heavy. It starts the dispatcher for executing futures including actors. It also starts the scheduler which is going to tick every few milliseconds. Multiple dispatchers and schedulers for the same application don't really add any benefit from the perspective of their roles.

Probably the main disadvantage is that is would mean you'd have separate actor trees with separate supervision. Using a single actor system with a single supervision hierarchy means that your application is wholly self aware and can self heal more effectively.

From your perspective what did you see as the advantages of multiple systems per application? I can help to see if we can cover these in a single system application, or multiple single system applications/microservices.

Always happy to help.

thedavidmeister commented 6 years ago

mostly the ability to have different protocols for different actors

leenozara commented 6 years ago

You could use an enum that includes all your different types that your actors need to receive. Then on receive you can match and just use the types in the enum that you're expecting to receive.

At first this might seem slightly clunky but you can hide most of that away by defining a protocol enum in lib.rs, main.rs or a separate protocol.rs. You can also bring the protocol enum into scope by using use Protocol::* so then you don't need to type Protocol::MyType each time and instead can simply type MyType, for example.

My gut instinct is that all components (actors) of an application should use the same protocol to communicate. It might be that later in development one actor needs to react to another actor's actions by subscribing to a channel and listening for what the other actor is publishing. Basically, if all your actors are using the same "language" to interact it makes for a more future proof design.

That, plus as I mentioned, each actor system is going to start up a thread pool, a scheduler, etc. It can get heavy if you have multiple systems.

I saw your other issue suggesting a Slack channel. There is a Gitter channel but it's not been used and your Slack suggestion might be better. Certainly better to move these type of conversations to some type of chat. I'll check and see what other folks are using for open source chat.

Thanks @thedavidmeister , I hope some of my answer makes sense.

thedavidmeister commented 6 years ago

so all this should be in the docs somewhere i think

i'll try out the enum idea. will need to get progressively sophisticated when relying on riker more.

zippy commented 6 years ago

hey @leenozara we use mattermost as our open source slack alternative...