其他
设计领域错误处理时,按受众与可恢复性分类并选择重试/降级/熔…
在设计领域错误类型与恢复策略时,帮助按受众和可恢复性对错误分类,并落地重试、降级、熔断等恢复模式。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 52/100 ×0.15
适用场景
设计领域错误处理时,按受众与可恢复性分类通用
解决思路
- 先问核心问题:谁需要处理这个错误,以及他们应如何恢复;设计错误类型前先判断是面向用户还是内部、是否可恢复、需要什么调试上下文。
- 按受众与恢复方式对错误分类:面向用户(引导操作,如 InvalidEmail、NotFound)、内部(开发者调试,如 DatabaseError、ParseError)、系统(运维监控告警,如 ConnectionTimeout、RateLimited)、瞬时(自动化重试,如 NetworkError、ServiceUnavailable)、永久(人工排查,如 ConfigInvalid、DataCorrupted)。
- 设计错误类型前思考三个# 问题:谁看到这个错误(终端用户→友好可操作消息,开发者→详细可调试,运维→结构化可告警);能否恢复(瞬时→带退避重试,可降级→回退值,永久→快速失败并告警);需要什么上下文(调用链→anyhow::Context,请求 ID→结构化日志,输入数据→错误负载)。
- 向上追溯到领域约束(Layer 3):例如处理支付失败时,追问业务重试规则、查 domain-fintech 事务要求、查 SLA 可用性要求;重试策略追溯 domain-* 问可接受延迟,用户体验问用户应看到什么消息,合规问必须记录什么审计日志。
- 向下追溯到实现(Layer 1):需要类型化错误→用 thiserror(库)与 Error enum 设计;需要错误上下文→用 anyhow::Context 与 tracing 字段日志;需要重试逻辑→用异步重试模式与 tokio-retry、backoff 等 crate。
- 按恢复模式选择实现:瞬时失败用重试(指数退避);降级模式用回退(缓存/默认值);级联失败用熔断器(failsafe-rs);慢操作用超时(tokio::time::timeout);隔离用舱壁(独立线程池)。
- 定义错误层级:用 thiserror 派生 AppError 枚举,区分面向用户(Validation)、瞬时/可重试(ServiceUnavailable,带 source)、内部(Internal,记录详情但对外显示通用消息),并实现 is_retryable() 判断是否可重试。
- 实现重试模式:用 tokio_retry 的 Retry 与 ExponentialBackoff,从 100ms 起、max_delay 10s、最多 5 次,包装异步闭包执行。
- 避免常见错误:不要所有错误用同一个(无行动性,应按受众分类);不要重试一切(浪费资源,只重试瞬时错误);不要无限重试(自我 DoS,应设最大次数+退避);不要暴露内部错误(安全风险,应给用户友好消息);不要无上下文(难调试,应处处 .context())。
- 避免反模式:不要用字符串错误(无结构,应用 thiserror 类型);不要对可恢复错误用 panic!(体验差,应用带上下文的 Result);不要忽略错误(静默失败,应记录或传播);不要到处用 Box<dyn Error>(丢失类型信息,应用 thiserror);不要在 happy path 中产生错误(影响性能,应尽早校验)。
适用边界 · 注意事项
- 不涉及错误处理设计、只需基础错误处理语法时(应看 m06-error-handling)
- 不涉及重试实现细节时(应看 m07-concurrency)
- 不涉及领域建模或面向用户 API 设计时(应看 m09-domain 或 domain-*)