
The Actor Model in Rust With Tokio Tasks and Channels
An actor is a task that owns its data and processes messages one at a time. Channels replace locks, and a handle type hides the plumbing.
Tag
33 posts

An actor is a task that owns its data and processes messages one at a time. Channels replace locks, and a handle type hides the plumbing.

An event bus lets parts of a program react to things without knowing about each other. Tokio's broadcast channel gives a small, typed one with built-in handling for slow subscribers.

A limiter is a function of time, so tests should control time. Assert the boundaries: the last allowed request, the first rejected one and the moment capacity returns.

A chat room is a one to many fan out. Tokio's broadcast channel gives each client its own receiver, and lagging clients are handled for you.

The core of every network service is an accept loop that spawns a task per connection. This walks through an echo server and a line protocol with Tokio, then adds limits.

tokio::spawn demands Send because tasks can move between threads. LocalSet pins tasks to one thread so Rc, RefCell and other !Send types can cross awaits.

The default of one worker per core is right for most services. Change it when a container limit misleads Tokio, or when measurements show queueing or contention.

The numbers that tell you a runtime is struggling are queue depth, worker busy time and poll counts. Tokio exposes them, and a small task exports them to Prometheus.

A hang is usually one of four things: a blocked runtime thread, a lock held across an await, a future that never wakes or a channel nobody closes. Here is the order to check them.

Use Tokio runtime and task metrics to see worker busy time, scheduling delay, queue depth and slow polls. Export them, read the numbers that matter and tell blocking code from a genuine lack of capacity.

Retry and timeout code is full of delays, and sleeping in tests makes them slow and flaky. Use Tokio paused time, a scripted flaky dependency and an injected backoff to test every path in milliseconds.

Make shutdown testable by taking a shutdown future instead of listening for signals inside the server. Assert that in-flight requests finish, new ones are refused and the process exits within a deadline.