mcpField
M
m13-domain-error

m13-domain-error

github.com/actionbook開発1.6k3.3k 回インストール9 週間前に更新
リポジトリ

m13-domain-error について

Rust 開発者向けのエラー設計スキルです。対象者、回復可能性、デバッグに必要な情報に基づくエラー分類と、適切な回復方法を示します。

主な機能

  1. 01対象者と回復方法によるエラー分類
  2. 02一時的なエラーと永続的なエラーの区別
  3. 03リトライ、フォールバック、タイムアウトの例
  4. 04診断情報と安全なメッセージの重視

活用シーン

  1. 01アプリケーションのエラー型の設計
  2. 02サービス障害時のリトライ方針の検討
  3. 03ログとユーザー向けエラーの改善

インストール

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

$npx skills add https://github.com/actionbook/rust-skills --skill m13-domain-error

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

詳細

ドメインエラー戦略

レイヤー 2:設計上の選択

中心となる問い

このエラーに対処する必要があるのは誰で、どのように復旧すべきでしょうか?

エラー型を設計する前に、次の点を確認します。

  • ユーザー向けですか、それとも内部向けですか?
  • 復旧は可能ですか?
  • デバッグにはどのようなコンテキストが必要ですか?

エラーの分類

エラーの種類対象復旧方法例
ユーザー向けエンドユーザー対応を案内するInvalidEmail、NotFound
内部向け開発者デバッグ情報を提供するDatabaseError、ParseError
システム運用/SRE監視/アラートConnectionTimeout、RateLimited
一時的自動化処理再試行NetworkError、ServiceUnavailable
恒久的人間調査ConfigInvalid、DataCorrupted

検討のための問い

エラー型を設計する前に、次の点を確認します。

  1. このエラーを誰が見ますか?

    • エンドユーザー → 親しみやすく、対応につながるメッセージ
    • 開発者 → 詳細で、デバッグ可能な情報
    • 運用担当者 → 構造化され、アラート可能な情報
  2. 復旧できますか?

    • 一時的 → バックオフを伴う再試行
    • 劣化可能 → フォールバック値
    • 恒久的 → 速やかに失敗し、アラートを出す
  3. どのようなコンテキストが必要ですか?

    • 呼び出しチェーン → anyhow::Context
    • リクエスト ID → 構造化ログ
    • 入力データ → エラーペイロード

上位への追跡 ↑

ドメインの制約へ(レイヤー 3):

"How should I handle payment failures?"
    ↑ Ask: What are the business rules for retries?
    ↑ Check: domain-fintech (transaction requirements)
    ↑ Check: SLA (availability requirements)
質問追跡先確認事項
再試行ポリシーdomain-*再試行時に許容できるレイテンシはどの程度ですか?
ユーザー体験domain-*ユーザーにはどのようなメッセージを表示すべきですか?
コンプライアンスdomain-*監査のために何をログに記録する必要がありますか?

下位への追跡 ↓

実装へ(レイヤー 1):

"Need typed errors"
    ↓ m06-error-handling: thiserror for library
    ↓ m04-zero-cost: Error enum design

"Need error context"
    ↓ m06-error-handling: anyhow::Context
    ↓ Logging: tracing with fields

"Need retry logic"
    ↓ m07-concurrency: async retry patterns
    ↓ Crates: tokio-retry, backoff

クイックリファレンス

復旧パターン条件実装
再試行一時的な障害指数バックオフ
フォールバック劣化モードキャッシュ値/デフォルト値
サーキットブレーカー障害の連鎖failsafe-rs
タイムアウト処理に時間がかかる場合tokio::time::timeout
バルクヘッド分離個別のスレッドプール

エラー階層

#[derive(thiserror::Error, Debug)]
pub enum AppError {
    // User-facing
    #[error("Invalid input: {0}")]
    Validation(String),

    // Transient (retryable)
    #[error("Service temporarily unavailable")]
    ServiceUnavailable(#[source] reqwest::Error),

    // Internal (log details, show generic)
    #[error("Internal error")]
    Internal(#[source] anyhow::Error),
}

impl AppError {
    pub fn is_retryable(&self) -> bool {
        matches!(self, Self::ServiceUnavailable(_))
    }
}

再試行パターン

use tokio_retry::{Retry, strategy::ExponentialBackoff};

async fn with_retry<F, T, E>(f: F) -> Result<T, E>
where
    F: Fn() -> impl Future<Output = Result<T, E>>,
    E: std::fmt::Debug,
{
    let strategy = ExponentialBackoff::from_millis(100)
        .max_delay(Duration::from_secs(10))
        .take(5);

    Retry::spawn(strategy, || f()).await
}

よくある間違い

間違い問題点改善策
すべて同じエラーにする対応につながらない対象に応じて分類する
すべてを再試行するリソースの浪費一時的なエラーのみ再試行する
無限に再試行する自己 DoS を招く最大試行回数とバックオフを設定する
内部エラーを公開するセキュリティリスクユーザーにわかりやすいメッセージを表示する
コンテキストがないデバッグが困難あらゆる箇所で .context() を使う

アンチパターン

アンチパターン問題点改善策
文字列エラー構造がないthiserror の型を使う
回復可能なケースで panic! を使うUX が悪いコンテキストを含む Result を使う
エラーを無視する失敗が表面化しないログに記録するか、伝播させる
あらゆる箇所で Box を使う型情報が失われるthiserror を使う
正常系の処理でエラーが発生するパフォーマンスの低下早期に検証する

関連スキル

条件参照先
エラー処理の基本m06-error-handling
再試行の実装m07-concurrency
ドメインモデリングm09-domain
ユーザー向け APIdomain-*

コメント