spawned_concurrency/lib.rs
1//! Actor framework for Rust, inspired by Erlang/OTP.
2//!
3//! `spawned-concurrency` provides an actor model where concurrency logic is
4//! separated from business logic. Define message interfaces with `#[protocol]`,
5//! implement handlers with `#[actor]`, and call methods directly on actor references.
6//!
7//! # Quick Start
8//!
9//! ```ignore
10//! use spawned_concurrency::tasks::{Actor, ActorStart, Context, Handler};
11//! use spawned_concurrency::{actor, protocol, Response};
12//!
13//! #[protocol]
14//! pub trait GreeterProtocol: Send + Sync {
15//! fn greet(&self, name: String) -> Response<String>;
16//! }
17//!
18//! pub struct Greeter;
19//!
20//! #[actor(protocol = GreeterProtocol)]
21//! impl Greeter {
22//! pub fn new() -> Self { Greeter }
23//!
24//! #[request_handler]
25//! async fn handle_greet(&mut self, msg: greeter_protocol::Greet, _ctx: &Context<Self>) -> String {
26//! format!("Hello, {}!", msg.name)
27//! }
28//! }
29//! ```
30//!
31//! # Core Concepts
32//!
33//! **Protocols** — A `#[protocol]` trait defines the message interface. The macro generates:
34//! - One message struct per method (in a snake_case submodule)
35//! - A type-erased reference type (`XRef = Arc<dyn Protocol>`)
36//! - Blanket `impl Protocol for ActorRef<A>` so you can call methods directly
37//!
38//! Return types determine message kind:
39//! - [`Response<T>`] — request, works in both async and sync modes
40//! - `Result<(), ActorError>` — fire-and-forget send, returns send result
41//! - No return type — fire-and-forget send
42//!
43//! **Actors** — `#[actor]` on an impl block generates `impl Actor` and `Handler<M>`
44//! impls from annotated methods (`#[request_handler]`, `#[send_handler]`, `#[handler]`).
45//! Lifecycle hooks use `#[started]` and `#[stopped]`.
46//!
47//! **Type-Erased References** — Each protocol generates an `XRef` type alias
48//! (e.g., `NameServerRef = Arc<dyn NameServerProtocol>`) and a `ToXRef` converter
49//! trait. This lets actors accept protocol references without knowing the concrete
50//! actor type — useful for cross-actor communication patterns.
51//!
52//! # Modules
53//!
54//! - [`tasks`] — async actor runtime (requires tokio)
55//! - [`threads`] — blocking actor runtime (native OS threads)
56//! - [`registry`] — global name-based actor registry
57//! - [`response`] — `Response<T>` unified wrapper for request-response
58//! - [`error`] — `ActorError` type
59//! - [`message`] — `Message` trait for defining message types
60//!
61//! # Choosing `tasks` vs `threads`
62//!
63//! Both modules provide identical `Actor`, `Handler<M>`, `ActorRef<A>`, and
64//! `Context<A>` types. Use `tasks` when you need async I/O or high actor counts.
65//! Use `threads` for CPU-bound work or when you want to avoid an async runtime.
66//! Switching requires changing imports and adding/removing `async`/`.await`.
67//!
68//! # Advanced
69//!
70//! - [`message::Message`] trait for manual message definitions without `#[protocol]`
71//! - `Recipient<M>` (`Arc<dyn Receiver<M>>`) for type-erased per-message references
72//! - [`tasks::Backend`] enum for choosing async runtime, blocking pool, or OS thread
73
74pub mod error;
75pub mod message;
76pub mod registry;
77pub mod response;
78pub mod tasks;
79pub mod threads;
80
81pub use error::ActorError;
82pub use response::Response;
83pub use spawned_macros::{actor, protocol};