Reference
API Overview
All the key types, traits, and macros in one place. For complete API documentation, see docs.rs/acton-reactive.
Core Types
ActonApp
The entry point. Its only job is to boot the system and hand you an ActorRuntime.
let mut runtime = ActonApp::launch_async().await;
| Method | Description |
|---|---|
launch_async().await | Start a new actor system (use this in async contexts) |
launch() | Start from a sync context. Panics if called inside a Tokio runtime. |
ActorRuntime
What launch_async() returns. This is where actor creation, the broker, shutdown, and IPC live.
| Method | Description |
|---|---|
new_actor::<T>() | Create an actor builder (default name) |
new_actor_with_name::<T>(name) | Create a named actor builder |
new_actor_with_config::<T>(config) | Create a builder from an ActorConfig |
spawn_actor::<T>(config, setup) | Create, configure, and start in one call |
spawn_actor_with_setup_fn::<T>(config, setup_fn) | As above, with an async setup closure |
broker() | Access the message broker |
actor_count() | Number of top-level actors |
shutdown_all().await | Graceful shutdown of the whole system |
ipc_registry() | Access IPC type registry |
ipc_expose(name, handle) | Expose actor for IPC. Returns Result<(), IpcNameInUse>; it no longer replaces an existing registration |
ipc_hide(name) | Remove IPC exposure |
ipc_lookup(name) | Find an IPC-exposed actor |
start_ipc_listener().await | Start IPC listener (default config) |
start_ipc_listener_with_config(cfg).await | Start IPC listener with custom config |
IPC methods require the ipc feature.
Actor Builder
ManagedActor<Idle, T> — configures an actor before spawning.
Handler-registration methods take &mut self and return &mut Self, while start() consumes the builder. So configure first, then start — you can't chain straight through into .start():
let mut builder = runtime.new_actor::<Counter>();
builder
.mutate_on::<Increment>(handler)
.act_on::<GetCount>(handler);
let handle = builder.start().await;
| Method | Description |
|---|---|
mutate_on::<M>(handler) | Register async state-changing handler |
mutate_on_sync::<M>(handler) | Register sync state-changing handler (no future allocation) |
act_on::<M>(handler) | Register async read-only handler |
act_on_sync::<M>(handler) | Register sync read-only handler (no future allocation) |
try_mutate_on::<M, T, E>(handler) | Async state-changing handler returning Result<T, E> |
try_act_on::<M, T, E>(handler) | Async read-only handler returning Result<T, E> |
on_error::<M, E>(handler) | Handle error E returned by a try_* handler for message M |
before_start(hook) | Lifecycle hook before the message loop starts |
after_start(hook) | Lifecycle hook after the message loop starts |
before_stop(hook) | Lifecycle hook before shutdown begins |
after_stop(hook) | Lifecycle hook after the message loop ends |
create_child(name) | Build a child actor under this one (Idle only — not available inside a handler) |
expose_for_ipc() | Expose actor for IPC using its ERN root name |
start().await | Spawn the actor, consuming the builder; returns its ActorHandle |
handle() | Get the handle before starting |
ActorHandle
Reference to a running actor.
handle.send(Message).await;
handle.stop().await.ok();
| Method | Description |
|---|---|
send(msg).await | Fire-and-forget message |
ask(request).await | Send a request and wait for the reply |
ask_with_timeout(request, dur).await | ask with an explicit deadline |
broadcast(msg).await | Publish to the broker for all subscribers |
stop().await | Stop the actor |
subscribe::<M>().await | Subscribe to broadcast messages |
unsubscribe::<M>() | Unsubscribe from broadcast messages (fire-and-forget) |
unsubscribe_async::<M>().await | Unsubscribe, awaiting delivery of the request to the broker |
reply_address() | Get this actor's address, for use as a return address |
create_envelope(recipient) | Create an envelope from this actor to recipient |
supervise_with::<S>(&runtime, config, blueprint).await | Register a child with a blueprint; returns SupervisedChild. The framework restarts it |
supervise(child).await | Adopt an already-built actor for cascading shutdown. No blueprint, so never restarted |
unsupervise(&ern).await | Retire the record and stop the child, dropping its IPC names |
release(&ern).await | Retire the record and hand the child back still running |
children() | Children supervised through this actor's handles — every clone shares one map; handles go stale across a restart |
find_child(&ern) | Look up a direct child by ERN, with the same caveat |
id() | Get actor's identifier (Ern) |
name() | Get actor's root name |
ask and Request
ask sends a request and waits for the reply. A message becomes askable by implementing Request, which names the reply through an associated type:
impl Request for GetCount {
type Response = Count;
}
let count = handle.ask(GetCount).await?;
Because inboxes are FIFO, a completed ask also proves every message sent to that actor beforehand has been processed. Handlers are unchanged: they answer through the reply envelope, and an actor cannot tell an ask from a send.
ask always finishes, backed by a 30-second DEFAULT_ASK_TIMEOUT. Outcomes come back as AskError, which is #[non_exhaustive]:
| Variant | Meaning |
|---|---|
NoReply | Delivered, but no answer is coming |
TimedOut { after } | The reply address is still live; the deadline expired |
Undeliverable | The inbox was already closed |
Cancelled | Delivery was abandoned during shutdown |
UnexpectedReply | The handler answered with a type the request does not declare |
PeerRejected { code, detail } | (IPC) The peer refused before dispatch; a retry is safe |
TransportFailed { detail } | (IPC) The connection failed; whether it was processed is unknown |
Do not ask from inside a mutate_on handler. Mutable handlers are awaited inline on the message loop, so waiting for a reply stops the actor from processing the message that would produce it.
SupervisedChild
A reference to a supervised child that survives its restarts. ActorHandle names one incarnation and goes stale; SupervisedChild reads a status channel its supervisor publishes to.
| Method | Description |
|---|---|
current() | Handle for the incarnation running right now |
wait_running().await | Block until an incarnation is up; errors once escalated |
wait_generation(gen).await | Block until a specific incarnation is up |
status() | The published SupervisionStatus: state, generation, last reason |
SupervisionState is Starting, Running, RestartPending, Restarting, Down (will not come back), or Escalated (allowance exhausted).
FlushBroadcasts
A barrier for broadcasts. broadcast completes when the broker has the message, not when subscribers do, and a broadcast carries no reply address for a subscriber to answer.
broker.ask(FlushBroadcasts).await?; // answers BroadcastsFlushed
The reply cannot arrive until every earlier broadcast is sitting in every subscriber's inbox. That is delivery, not completion: to know a particular subscriber has handled it, ask that subscriber afterwards.
ActorRuntime::shutdown_all flushes the broker before signalling anything, so broadcasting and then shutting down is not a race.
Reply
Builds the future a handler must return.
| Method | Used with | Description |
|---|---|---|
Reply::ready() | mutate_on, act_on | Complete immediately, no async work |
Reply::pending(future) | mutate_on, act_on | Wrap an async block |
Reply::try_pending(future) | try_mutate_on, try_act_on | Wrap an async block returning Result |
Reply::try_ok(value) | try_mutate_on, try_act_on | Immediate success |
Reply::try_err(error) | try_mutate_on, try_act_on | Immediate failure |
Handler futures require Send
As of v10, handler and lifecycle futures require Send + 'static, without Sync. Await third-party I/O directly inside Reply::pending or Reply::try_pending. Reusable handler closures, actor state, and messages retain their Sync requirements. Explicitly typed named handlers must remove Sync from their boxed future return signature. See Integration.
MessageContext
The second argument every handler receives — the message plus its routing information. Written ctx or envelope in examples.
| Method | Description |
|---|---|
message() | Reference to the message payload (an accessor, not a field) |
reply_envelope() | OutboundEnvelope addressed back to the sender |
origin_envelope() | OutboundEnvelope representing where the message came from |
new_envelope(&address) | OutboundEnvelope to a different recipient, keeping this actor as the return address |
MessageContext is not exported from the prelude — you don't normally need to name it, since handlers are closures and the type is inferred.
OutboundEnvelope
A message prepared for sending. This is what reply_envelope() and create_envelope() hand you.
| Method | Description |
|---|---|
send(msg).await | Send a message via this envelope |
try_send(msg).await | Send, returning Err instead of waiting if the inbox is full |
reply(msg) | Synchronous send (discouraged — prefer send) |
reply_to() | The return address |
recipient() | The recipient address, if any |
Macros
#[acton_actor]
Marks a struct as actor state.
#[acton_actor]
struct Counter {
count: i32,
}
#[acton_message]
Marks a struct as a message.
#[acton_message]
struct Increment;
#[acton_message(ipc)] // Enable IPC serialization
struct GetValue;
#[acton_main]
Sets up the async runtime.
#[acton_main]
async fn main() {
let runtime = ActonApp::launch_async().await;
// ...
}
Prelude
Import everything:
use acton_reactive::prelude::*;
| Category | Items |
|---|---|
| Macros | acton_actor, acton_message, acton_main |
| System | ActonApp, ActorRuntime, ActorConfig, Broker, BrokerRef, ParentRef |
| Actors | ManagedActor, Idle, Started, ActorHandle |
| Handlers | Reply |
| Request/reply | AskError, DEFAULT_ASK_TIMEOUT |
| Messages | BrokerRequest, BrokerRequestEnvelope, MessageAddress, OutboundEnvelope, ChildTerminated, SystemSignal, FlushBroadcasts, BroadcastsFlushed |
| Supervision | SupervisedChild, SupervisionStatus, SupervisionState, SupervisionError, Escalation, RestartPolicy, TerminationReason, SupervisionStrategy, SupervisionDecision, RestartLimiter, RestartLimiterConfig, RestartLimitExceeded, RestartStats, RestartGeneration, ChildIndex, BackoffDelay, MAX_SUPERVISION_DEPTH |
| Supervision events | ChildSupervised, ChildRestarted, SupervisionEscalated |
| Traits | ActonMessage, ActorHandleInterface, Broadcaster, Request, Subscribable, Subscriber |
| Re-exports | everything from acton_ern, plus async_trait and tokio |
IPC (ipc feature) | IpcClient, IpcClientConfig, IpcConfig, IpcEnvelope, IpcError, IpcResponse, IpcListenerHandle, IpcListenerStats, IpcTypeRegistry, RemoteActorRef, ShutdownResult, and the RemoteRequest trait |
Note that MessageContext is deliberately not in the prelude; handlers receive it as an inferred closure parameter.