Although the project structure can be arbitrary, it looks reasonable to provide some advices here:
- Use a separate crate for every actor group.
- It speeds up a build time.
- It helps to isolate code.
- Use separate crates for protocols, where messages are defined. Internal messages (timer ticks, inner group messages etc) are defined inside a group's crate.
- Actor crates shouldn't depend on each other. Instead, they should depend on protocol crates.
- It helps to achieve loosely coupling.
- Prefer integration tests (
tests/) over unit tests (
mod tests). Unit tests are still fine for internal structures.
- Integration tests use no implementation details and relies only on protocols.
- Store libraries (additional code potentially used by multiple actors) separately from actors' code. It's ok to depends on protocols in that code, but don't depend on actors.
libs/in the example below.
- Store different parts of a group in dedicated files, it siplifies navigation:
exec()and message handling in
- An inner-group router in
- A group's config in
- Store topology definitions separately from actors' code. Services can share actors. Also, it's a good place for additional files like systemd units and so on.
services/in the example below.
actors/ <actor_name_1>/ src/ mod.rs actor.rs config.rs router.rs tests/ helpers.rs test_<name_1>.rs test_<name_2>.rs Cargo.toml <actor_name_2>/ protocol/ src/ lib.rs Cargo.toml libs/ <lib_name_1>/ <lib_name_2>/ services/ <service_name_1>/ <service_name_2>/ Cargo.toml Cargo.lock rustfmt.toml