원클릭으로
async-rust
Async Rust Best Practices guidance for Fortress Rollback. Use when Writing async code, debugging futures, Send/Sync issues.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Async Rust Best Practices guidance for Fortress Rollback. Use when Writing async code, debugging futures, Send/Sync issues.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Crate Publishing guidance for Fortress Rollback. Use when Publishing to crates.io, version bumps, release checklist.
Changelog Practices guidance for Fortress Rollback. Use when Writing CHANGELOG entries, deciding what to document.
Design Decision Log Pattern guidance for Fortress Rollback. Use when Architectural decisions, design alternatives, superseding prior choices.
Repository-wide engineering policy and project context for Fortress Rollback. Use when implementing, diagnosing, reviewing, testing, documenting, or releasing changes in this repository.
GitHub Actions Best Practices guidance for Fortress Rollback. Use when Writing GitHub Actions workflows, CI debugging, actionlint, caching.
Workspace Organization guidance for Fortress Rollback. Use when Organizing workspace, splitting crates, module structure decisions.
| name | async-rust |
| description | Async Rust Best Practices guidance for Fortress Rollback. Use when Writing async code, debugging futures, Send/Sync issues. |
Async code should never spend a long time without reaching an
.await.
Task switching only happens at .await points. Long-running code between awaits blocks the runtime thread.
| Scenario | Solution |
|---|---|
| Short blocking (<100us) | Run inline |
| File system ops | spawn_blocking or tokio::fs |
| CPU-bound computation | spawn_blocking or rayon |
| Forever-running blocking | Dedicated std::thread::spawn |
let result = tokio::task::spawn_blocking(|| expensive_sync_operation()).await?;
| Pattern | Primitive | Use Case |
|---|---|---|
| Sequential | a.await; b.await | Dependent operations |
| Concurrent, wait all | join! / try_join! | Independent operations |
| First wins | select! | Racing, timeouts |
| Spawn independent | tokio::spawn | Fire-and-forget |
| Limit concurrency | Semaphore | Rate limiting |
| Process stream | StreamExt::for_each_concurrent | Bounded parallel processing |
| Dynamic futures | FuturesUnordered / JoinSet | Variable number of tasks |
match timeout(Duration::from_secs(5), fetch_data()).await {
Ok(result) => handle(result?),
Err(_) => return Err(Error::Timeout),
}
| Channel | Use Case |
|---|---|
mpsc | Multiple producers, single consumer |
oneshot | Send exactly one value |
broadcast | All consumers receive all messages |
watch | Single changing value |
.await points: Use tokio::sync::Mutex.await while held): std::sync::Mutex is fineUse CancellationToken + TaskTracker:
let token = CancellationToken::new();
tokio::spawn(async move {
tokio::select! {
_ = token.cancelled() => { break; }
result = do_work() => { handle(result); }
}
});
token.cancel(); // trigger shutdown
'staticPrefer owned data or Arc for shared read-only data.
Use bounded channels (mpsc::channel(100)) to prevent memory exhaustion. Never unbounded_channel in production without good reason.
| Pitfall | Fix |
|---|---|
#[track_caller] on async fn | Not supported; extract a sync helper or remove the attribute |
std::thread::sleep in async | tokio::time::sleep().await |
Forgetting to .await futures | Futures are lazy -- nothing happens without await |
std::sync::Mutex held across .await | Use tokio::sync::Mutex or release before await |
| Spawning millions of tasks | Use for_each_concurrent with limit |
| Ignoring task panics | Check JoinHandle result |
| Dropping future cancels it | Use guards for cleanup |
| std | Async Alternative |
|---|---|
std::thread::sleep | tokio::time::sleep |
std::fs::* | tokio::fs::* |
std::net::* | tokio::net::* |
std::sync::Mutex (across await) | tokio::sync::Mutex |
| Blocking FFI | spawn_blocking |
#[tokio::test]
async fn test_fn() { /* ... */ }
#[tokio::test(start_paused = true)]
async fn test_timeout() {
// Time is paused -- sleeps complete instantly
tokio::time::sleep(Duration::from_secs(3600)).await;
}
Async: High concurrency, I/O-bound, event-driven, library requires it. Sync/Threads: CPU-bound (use rayon), simple I/O, simpler debugging, blocking FFI.