mcpField
T
tokio-async-code-review

tokio-async-code-review

github.com/existential-birdsテスト・品質8590 回インストール11 週間前に更新
リポジトリ

tokio-async-code-review について

tokio-async-code-reviewは、Tokioを使うRust非同期コードのレビュー向けスキルです。ランタイム、ブロッキング処理、タスク、同期プリミティブ、チャネルを扱い、指摘には根拠を求めます。

主な機能

  1. 01Tokio の依存関係と機能フラグの確認
  2. 02ランタイムモデルの特定
  3. 03非同期コード内のブロッキング処理の調査
  4. 04タスクと同期プリミティブのレビュー
  5. 05チャネル形式とキャンセル安全性の確認

活用シーン

  1. 01Tokio の機能フラグとランタイム設定のレビュー
  2. 02非同期関数内のブロッキング呼び出しの発見
  3. 03タスクハンドルとエラー処理の確認
  4. 04ロック、チャネル、キャンセル動作の評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/existential-birds/beagle --skill tokio-async-code-review

インストール後、Claude Code で/tokio-async-code-reviewを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
channels.md
pinning-cancellation.md
sync-primitives.md
task-management.md

詳細

Tokio の非同期コードレビュー

レビューワークフロー

  1. Cargo.toml を確認する — tokio のフィーチャーフラグ(full、rt-multi-thread、macros、sync など)を確認します。フィーチャーが不足していると、原因の分かりにくいコンパイルエラーが発生します。
  2. ランタイムの設定を確認する — #[tokio::main] と手動でのランタイム構築のどちらが使われていますか? マルチスレッドとカレントスレッドのどちらですか?
  3. ブロッキング処理を探す — 非同期関数内で std::fs、std::net、std::thread::sleep、CPU 負荷の高いループを検索します。
  4. チャネルの使い方を確認する — 通信パターンに適したチャネルの種類(mpsc、broadcast、oneshot、watch)を選びます。
  5. 同期プリミティブを確認する — 正しい種類のミューテックスが使われていること、ガードのライフタイムが適切であること、デッドロックの可能性がないことを確認します。

ゲート(結論を出す前に満たすべき客観的な条件)

レビュー対象の範囲について、順番に完了してください。該当するゲートを通過するまでは、Critical または Major と断定しないでください。

  1. 依存関係の確認 — tokio を提供するクレートの Cargo.toml(継承されている場合はワークスペースのものも)を読みます。合格条件: tokio のバージョンと有効なフィーチャーを記したメモがあること、または tokio への直接依存がないことと、その依存元(ワークスペース/パス)を明記していること。
  2. ランタイムモデル — ランタイムの構築箇所(#[tokio::main]、Runtime::builder、テスト、またはランタイムを所有しないライブラリ)を特定します。合格条件: フレーバー(multi_thread/current_thread/テストのみ/なし)と、その定義箇所を1行で示していること。
  3. ブロッキング処理の一覧 — レビュー対象のパスで、ブロッキング API(std::fs::、非同期ラッパーのない std::net::、std::thread::sleep、async fn 内の高負荷な CPU ループ)を検索します。合格条件: 検出箇所をそれぞれ path:line 形式(またはツールの出力抜粋)で列挙していること。または、検索後に「レビュー対象の非同期コードにブロッキングパターンは見つかりませんでした」と明記していること。
  4. プロトコル — review-verification-protocol スキルを読み込みます。合格条件: 指摘を報告する前に、そのスキルの合格条件を満たしていること(主張する問題について file:line の根拠を示すこと)。

出力形式

指摘事項は次の形式で報告してください。

[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.

クイックリファレンス

問題の種類参照先
タスクの生成、JoinHandle、構造化並行性references/task-management.md
Mutex、RwLock、Semaphore、Notify、Barrierreferences/sync-primitives.md
mpsc、broadcast、oneshot、watch のチャネルパターンreferences/channels.md
Pin、キャンセル、Future の内部構造、select!、ブロッキング処理との橋渡しreferences/pinning-cancellation.md

レビューチェックリスト

ランタイムの設定
  • Cargo.toml の Tokio フィーチャーが実際の使用状況と一致している
  • ランタイムのフレーバーがワークロードに適している(I/O バウンドには multi_thread、より単純なケースには current_thread)
  • 非同期テストには #[tokio::test] を使用している(手動でランタイムを構築していない)
  • 本番環境に適したワーカースレッド数を設定している
タスク管理
  • spawn の戻り値(JoinHandle)を追跡しており、暗黙に破棄していない
  • CPU 負荷の高い処理や同期 I/O 処理には spawn_blocking を使用している
  • タスクがキャンセルに対応している(CancellationToken、select!、またはシャットダウンチャネルを使用)
  • JoinError(タスクのパニックまたはキャンセル)を単にアンラップせず、適切に処理している
  • tokio::select! の各分岐がキャンセルセーフである
  • 可能な場合は async-trait クレートではなく、トレイトでネイティブの async fn を使用している(Rust 1.75 以降で安定)
  • 非同期コンテキストにおける RPIT のライフタイムキャプチャを確認している — edition 2024 では -> impl Future がスコープ内のすべてのライフタイムをキャプチャするようになりました
同期プリミティブ
  • ロックを .await をまたいで保持する場合は tokio::sync::Mutex を使用し、短い非同期処理ではないセクションでは std::sync::Mutex を使用する
  • await ポイントをまたいでミューテックスガードを保持しない(デッドロックのリスク)
  • 同時実行操作の制限には Semaphore を使用する(場当たり的なカウンターは使用しない)
  • 読み取りが多いワークロード(読み取りが多く、書き込みの頻度が低い)では RwLock を使用する
  • シンプルなシグナリングには Notify を使用する(チャネルのオーバーヘッドは避ける)
  • 実行時に初期化されるシングルトンには、once_cell::sync::Lazy や lazy_static! の代わりに std::sync::LazyLock を使用する(Rust 1.80 以降で安定版)
  • エディション 2024 の一時値のスコープに照らして if let のロックガードパターンを確認する。一時値の破棄が早まり、借用の有効性が変わる場合がある
チャネル
  • パターンに合ったチャネル型を使用する:バックプレッシャーには mpsc、ファンアウトには broadcast、リクエスト/レスポンスには oneshot、最新値には watch
  • 有界チャネルの容量が適切である(小さすぎるとデッドロック、大きすぎるとメモリを消費する)
  • SendError / RecvError を処理する(相手側がドロップされたことを示す)
  • Broadcast の Lagged エラーを処理する(受信側が遅れている)
  • 受信側に完了を知らせるため、処理が終わったらチャネルの送信側をドロップする
タイマーとスリープ
  • std::thread::sleep の代わりに tokio::time::sleep を使用する
  • ハングする可能性のある操作を tokio::time::timeout で囲む
  • tokio::time::interval を正しく使用する(定期処理には .tick().await を使用する)

重大度の基準

重大
  • spawn_blocking を使わずに、非同期コンテキストでブロッキング I/O(std::fs::read、std::net::TcpStream)を行う
  • .await ポイントをまたいでミューテックスガードを保持する(デッドロックの可能性)
  • 非同期関数内で std::thread::sleep を使用する(ランタイムスレッドをブロックする)
  • バックプレッシャーが必要な箇所で非有界チャネルを使用する(OOM のリスク)
重要
  • JoinHandle を暗黙にドロップする(エラーの喪失、ゾンビタスク)
  • select! のキャンセル安全性を考慮していない
  • 用途に合わないミューテックス型(std と tokio)を使用する
  • ネットワーク操作や外部操作にタイムアウトがない
軽微
  • ごく小さな非同期ブロックに tokio::spawn を使用する(メリットよりオーバーヘッドが大きい)
  • 根拠なくチャネルバッファーを大きくしすぎる
  • #[tokio::main] で十分な箇所でランタイムを手動構築する
  • 競合が多く、tokio の非同期ミューテックスが有効な箇所で std::sync::Mutex を使用する
参考情報
  • tokio-util のユーティリティ(例:CancellationToken)の使用を提案する
  • サービス合成のための Tower ミドルウェアパターン
  • JoinSet による構造化並行性
  • async-trait クレートから、トレイト内のネイティブな async fn への移行
  • once_cell / lazy_static から std::sync::LazyLock への移行
  • 抑制を自己解消可能にするため、#[allow(lint)] の代わりに #[expect(lint)] を使用する

有効なパターン(指摘しないこと)

  • 短いクリティカルセクションでの std::sync::Mutex — ロック内に .await がない場合、tokio のドキュメントでも推奨されています
  • 明示的な join を伴わない tokio::spawn — 適切なシャットダウンシグナリングがあれば、バックグラウンドタスクとして有効です
  • 容量 1 のバッファーなしチャネル — 同期バリアとして有効です
  • シンプルなバイナリでの #[tokio::main(flavor = "current_thread")] — すべてのアプリでマルチスレッドランタイムが必要なわけではありません
  • spawn の前に行う Arc<T> の clone() — タスク内へ移動するために必要であり、不要な複製ではありません
  • 大容量の broadcast チャネル — lagged エラーのコストが高い場合(イベントソーシングなど)に有効です
  • async-trait を使わないトレイト内のネイティブな async fn — 1.75 以降で安定版です。dyn ディスパッチの場合には、引き続きこのクレートが有効です
  • -> impl Future の戻り値に付ける + use<'a> — ライフタイムのキャプチャを制限する、エディション 2024 の正しい厳密なキャプチャ構文です
  • 複雑な非同期型に対する #[expect(clippy::type_complexity)] — #[allow] の代わりとなる自己解消可能な方法であり、抑制が不要になった際に警告します

指摘を提出する前に

Gates の後、報告するすべての問題に review-verification-protocol スキルを適用してください(証拠と処置はそのスキルに従ってください)。

コメント