一键导入
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.