关于 maintainable-app
maintainable-app 是用于构建、修改和审查生产应用的技能,面向需要处理可靠性与运维问题的开发者。它围绕幂等、有限重试、故障恢复和可观测性,帮助应用从常见故障中自动恢复。
主要功能
- 01识别生产故障模式
- 02设计幂等操作与工作标识
- 03配置超时和有界重试
- 04规划队列与分布式流程恢复
- 05围绕状态转换设计可观测性
适用场景
- 01设计 Webhook、队列任务和定时作业
- 02处理外部 API 超时与重试
- 03审查应用故障恢复和运维信号
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jpcaparas/ skills --skill maintainable-app安装后在 Claude Code 中输入/maintainable-app确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdmetadata.jsonREADME.mdskill-card.prompt.mdagents/openai.yamlassets/.gitkeepevals/evals.jsonreferences/distributed-systems.mdgotchas.mdjobs-and-queues.mdobservability.mdprinciples.mdreview-rubric.mdsource-notes.mdscripts/analyze_app_resilience.pytest_skill.pyvalidate.pytemplates/resilience-review.md详细介绍
maintainable-app
构建、编辑和审查应用程序,使常见的生产故障能够自动恢复、有意降级,并留下足够的信号,让一位维护者了解发生了什么。
被动触发
当编码任务涉及面向生产环境的应用程序、后台工作进程、计划任务、Webhook、支付流程、导入/导出、通知、API 集成、数据库状态转换、缓存、文件上传、队列、cron、身份验证/会话流程、可观测性、日志记录、追踪、告警或可靠性行为时,在后台加载此技能。
对于小改动,保持轻量:静默地快速检查故障模式,然后只提及会影响实现的故障保护措施、边缘情况和可观测性决策。对源代码改动,也加载 {{ skill:maintainable-code }};如果有可用的测试技能,则在新增或修改测试时加载 {{ skill:maintainable-tests }}。
决策树
你正在构建或修改什么?
-
面向用户的请求、工作流或状态转换: 阅读
references/principles.md。在编写正常路径之前,明确故障状态、重试安全性、用户可见的降级方案和恢复路径。 -
队列、后台作业、cron、Webhook、导入/导出、电子邮件、支付扣款或通知: 阅读
references/jobs-and-queues.md。确保具备幂等性、唯一的工作标识、有界并发、重试限制、死信处理、过期工作的恢复机制和工作进程超时。 -
多个服务、外部 API、事件发布、分布式数据变更或异步工作流: 阅读
references/distributed-systems.md。设计超时、重试预算、outbox/inbox 处理、去重、协调和补偿操作。 -
日志、指标、追踪、告警、仪表板或故障诊断: 阅读
references/observability.md。对能解释用户影响和恢复情况的决策点进行监测,而不是为每行代码添加监测。 -
审查差异或实现计划: 使用
references/review-rubric.md。优先关注需要开发者手动介入的故障、重复副作用、卡住的状态、无上限的重试以及缺失的运维信号。 -
不确定从哪里开始: 阅读
references/principles.md,然后运行下面的自愈检查。
快速参考
| 情况 | 默认操作 |
|---|---|
| 浏览器重复提交、Webhook 重放、重试或工作进程重启 | 添加幂等键或确定性工作键,并持久化结果或状态转换 |
| 十位用户触发同一个高开销作业 | 按唯一作业键合并请求,为一个活动工作进程分配租约,返回现有作业状态,并公开进度 |
作业在 pending 或 running 状态停留过久 | 添加 expires_at 或基于心跳的过期检测、安全重试或故障转移,并写入审计日志 |
| 远程 API 调用 | 设置连接和请求超时,对可重试错误分类,使用带上限并加入抖动的退避策略,并在达到重试预算时停止 |
| 队列负载激增 | 缓冲工作、限制工作进程并发数、使用背压/速率限制,并保护共享依赖 |
| 数据库写入后的副作用 | 使用 outbox 或事务性交接;确保消费者具备幂等性 |
| 多步骤分布式工作流 | 明确建模状态,并添加协调或补偿操作 |
| 部分服务中断 | 优先降级价值较低的功能,并保留用户的核心任务 |
| 记录请求/作业进度 | 包含关联 ID、操作者、工作键、状态转换、尝试次数、依赖项、持续时间和结果 |
| 指标 | 跟踪延迟、流量、错误、饱和度、队列积压时长、重试次数、死信数量和过期工作 |
| 追踪 | 在跨边界调用和持久化异步交接处添加跨度,而不是在细小的本地辅助函数处添加 |
| 告警 | 仅在影响用户或自动化机制耗尽时触发呼叫告警;否则创建可检查的仪表板或工单 |
核心规则
- 将重试、重复投递、并发、延迟、部分故障、部署重启和过时状态视为正常输入,而非异常事故。
- 为每项成本高昂或会产生副作用的操作分配稳定标识。系统应能判断请求是新任务、重放,还是不同意图。
- 优先使用明确的状态机,而非松散的状态字符串。每种状态都需要定义允许的转换、负责人、超时、重试策略、终态结果和恢复行为。
- 先在应用中实现恢复,再将其写入人工操作手册。使用有界重试、过期任务清理器、协调任务、死信队列和安全的重新投递路径。
- 使用队列、租约、速率限制、隔舱和背压来限制影响范围。不要让某个噪声过大的工作流耗尽整个应用的资源。
- 在能够强制保证幂等性的边界处理副作用:数据库约束、唯一键、幂等性表、发件箱/收件箱表、提供方幂等键或队列去重。
- 只要工作跨越进程、网络、队列、数据库或提供方边界,就要设置超时。卡住的依赖应进入已知状态,并有明确的有界恢复路径。
- 黄金法则:每次面向生产环境的应用变更,都应首先考虑四项黄金信号:延迟、流量、错误和饱和度。只有在覆盖这些用户健康状况和容量问题后,才添加专用指标。
- 针对决策、状态转换、重试、丢弃的工作、降级行为和依赖边界记录日志并进行追踪。不要添加无法回答生产问题的遥测数据。
- 确保日志可安全保留和搜索。绝不要记录机密、令牌、原始支付详情、完整个人身份信息(PII)、会话 Cookie 或提供方凭据。
- 测试恢复路径。在重复请求、可重试故障、卡住的任务、依赖超时和过时状态都经过针对性验证或明确记录缺口之前,功能就尚未达到可投入运维的状态。
自愈检查
完成应用变更前,请检查:
| 检查项 | 通过条件 |
|---|---|
| 标识 | 重复请求、任务、Webhook 和事件都映射到稳定的幂等键或工作键 |
| 状态 | 非简单工作具有明确的待处理/运行中/成功/失败/已取消/过期行为 |
| 并发 | 共享资源具有唯一性约束、锁、租约、速率限制或工作线程上限 |
| 时间 | 远程调用、任务、锁和待处理状态都设有超时或过期时间 |
| 重试 | 对可重试错误进行分类,并设置有界次数和抖动;同时确保重复副作用安全 |
| 恢复 | 卡住、部分完成和失败的状态可以重试、协调、重新投递或转为终态,而无需开发者手动编辑数据 |
| 降级 | 可选依赖失效时,应用仍能保留最重要的用户任务 |
| 可观测性 | 日志、指标和追踪能够说明用户影响、工作标识、状态转换、尝试次数、依赖健康状况和恢复结果 |
| 告警 | 告警应在自动化耗尽或用户受到影响时触发,而非针对每次预期中的暂时性故障 |
| 测试 | 针对最可能发生的生产故障,提供专项测试、模拟或明确说明验证缺口 |
运行工作流
-
先进行侦察。 在设计弹性机制之前,先阅读相关处理程序、作业、架构、提供方适配器、队列配置、日志规范、仪表板和测试。
-
绘制故障图。 列出重复输入、并发输入、依赖项超时、提供方返回 429/5xx、工作进程崩溃、部署重启、数据库冲突、状态过期和部分完成。根据功能风险控制清单的范围。
-
选择恢复责任方。 确定由请求处理程序、队列工作进程、调度程序、协调作业、数据库约束、提供方幂等功能还是面向操作人员的工具负责每条恢复路径。
-
实现最小的持久化机制。 优先使用本地约束和现有框架原语。当故障模式确实足以构成理由时,再添加队列、锁、outbox 表、熔断器或看门狗。
-
为整个流程添加监测。 在状态转换和边界处添加结构化日志、指标和跟踪。明确写出每个信号要回答的具体问题。
-
验证故障行为。 在可行的情况下,针对重复输入、重试、超时、过期工作和依赖项降级行为运行定向测试或本地模拟。
-
如实报告。 说明已处理的边缘情况、添加的故障保护机制、添加的信号、运行的验证,以及剩余的运维风险。
可选辅助工具
将辅助工具用作快速扫描审查提示的工具,而非裁决依据:
python3 scripts/analyze_app_resilience.py /path/to/project
python3 scripts/analyze_app_resilience.py /path/to/project --json
它会标记可能缺少幂等性、重试/退避机制存在缺口、外部调用明显未设置超时、日志上下文不足、错误被吞掉,以及待处理状态缺少恢复机制等问题。扫描结果没有提示问题,并不能证明应用具备弹性;扫描结果提示很多问题,也不代表代码一定有错。
阅读指南
| 需求 | 阅读内容 |
|---|---|
| 自我修复的核心原则和故障映射 | references/principles.md |
| 作业、队列、webhook、cron、卡住的工作和重复工作 | references/jobs-and-queues.md |
| 重试、超时、幂等 API、outbox/inbox、saga 和协调 | references/distributed-systems.md |
| 日志、指标、跟踪、告警和仪表板 | references/observability.md |
| 基于严重程度审查弹性改动 | references/review-rubric.md |
| 常见陷阱和反模式 | references/gotchas.md |
| 研究来源和调整说明 | references/source-notes.md |
注意事项
- 重试不安全的工作可能引发你原本想要修复的故障。添加重试之前,先确保操作具有幂等性。
- 如果锁在工作进程完成之前就过期,仅有唯一作业并不足够。应协调锁 TTL、作业超时、可见性超时和重试窗口。
pending不是恢复策略。每个非终止状态都需要责任方和过期状态处理路径。- 如果日志没有关联 ID、工作键、尝试次数和结果,在单人维护者处理故障时往往帮不上忙。
- 可观测性并非越多越好。高基数、包含机密或无人查询的遥测数据会增加成本和风险,却无法改善恢复能力。
- 死信队列不是垃圾桶。它们需要告警、检查字段、重新投递规则,以及有害消息处理策略。
- 必须在故障发生前实现优雅降级。即使可选功能失效,核心任务仍应正常运行。