SuperAPI AI Directory

tokio

Coding & development

View repository

Updated 10-15 20:32

About this skill

Tokio

Tokio is the executor. Axum, sqlx, reqwest, and WS run on it. HTTP: axum. Production/shutdown: rust-axum-production. WS hub: rust-axum-websocket. Language: rust.

Do not switch to async-std/smol in an Axum API. Multi-thread (#[tokio::main]) is the service default; current_thread only if the binary already is like that (CLI, test).

Non-negotiable rules

  • Do not block workers: no heavy std::thread::sleep, std::fs , long std mutex, synchronous DNS/wait in the handler.
  • CPU/FS/legacy sync → spawn_blocking (or async crate). Network I/O → Tokio APIs/async.
  • Every task has an end: JoinHandle, JoinSet or cancellation. No spawn fire-and-forget of business work.
  • select! with fair cancellation; the branch that loses does not leave orphaned I/O (use AbortHandle / drop of the future / CancellationToken).
  • Context/request deadline: propagate cancel, do not ignore JoinHandle from the handler.

Boot

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // tracing, config, bind — rust-axum-production
    Ok(())
}
  • Runtime of axum::serve + graceful shutdown in main, not a second runtime.
  • Cargo features: rt-multi-thread, macros, net, sync, time — the ones the crate already requests. Do not full “just in case” if the project is lean.

Tasks

API When
tokio::spawn Async work tied to the runtime (fan-out, WS write loop)
spawn_blocking Short CPU, diesel sync, zip, bcrypt
JoinSet N tasks of the same unit; abort on drop
LocalSet !Send — rare in an API; do not use in an Axum handler without reason
  • 'static + Send in the spawn of the server. State: Arc.
  • Panic in task: JoinError; do not swallow it. await or abort on shutdown.

select, time, cancel

  • tokio::time::timeout / sleep — never thread::sleep.
  • select! biased: biased only with an invariant. I/O timeouts on the client (reqwest) and on the server (tower timeout).
  • tokio_util::sync::CancellationToken (or the project's) for the WS hub and workers. Dropping the token aborts children.

Channels

Channel Role
mpsc One consumer (WS writer, internal queue)
broadcast Fan-out (hub); lag → Lagged
watch Last value (config, ready)
oneshot One response

Capacity limited on the hot path. unbounded only with backpressure elsewhere (rust-axum-websocket).

Anti-patterns

  • block_on inside an async handler (deadlock in the runtime)
  • spawn per SQL query request (use the async pool)
  • std::sync::Mutex held across .await
  • Second #[tokio::main] in a test lib without #[tokio::test]
  • Busy loop without yield_now / channel

Integration with other skills

  • HTTP: axum
  • WS: rust-axum-websocket
  • Client: reqwest
  • Logs: tracing
  • Tests: rust-unit-testing (#[tokio::test])

Completion criteria

  • No blocking in the worker in new code
  • Tasks with join/cancel on shutdown
  • Channels with a bound or lag policy
  • timeout Tokio in the touched I/O
  • Single runtime aligned with Axum