Skip to content

feat(storage): 存储异常告警(连续失败才通知管理员,恢复有下文) - #44

Merged
worable233 merged 1 commit into
mainfrom
feat/storage-alert
Oct 25, 2026
Merged

worable233 merged 1 commit into
mainfrom
feat/storage-alert

Conversation

@worable233

Copy link
Copy Markdown
Owner

对标 #12.5 里「4 项缺失」的最后一项:对方 ossExceptionNotice() 每 5 分钟探一次对象存储,失败就通知管理员;我方 /ready 有存储探测,但探测结果只对探针可见,存储挂了没人收到通知。

不照抄对方的两处

  1. 抖一下就通知 → 「连续 3 次失败才告警」(5 分钟一次 ≈ 15 分钟延迟)。一次超时可能只是网络抖动,而管理员会被无意义告警训练成「不看了」
  2. 只报故障不报恢复 → 恢复也要「连续 2 次成功」才发,避免故障/恢复交替刷屏,同时让管理员知道要不要继续排查

实现

  • 新内核任务 storage.watch(5 分钟,与对方同频),createStorageWatch() 持有 failures/successes/alerted 三个计数;探测抛错按不可用处理,不向任务抛出(否则任务进死信被反复重试)。
  • 收件人用 listAdminUserIds():管理员在数据模型里不是 User 字段,而是权限组授予的 platform.admin;限时成员按读路径规则过滤过期行 —— 与 hasPermission 同一口径,否则过期的管理员权益会让告警一直发给无权的人。
  • 新增通知类型 admin.storage.unreachable / admin.storage.recovered 并登记在内建目录(「发出即声明」守门覆盖)。类型字面量写在 type: 位置而不是用模板串拼,否则会绕过 notification-type-coverage 扫描。

验证

  • tests/unit/storage-watch.test.ts 5 例:阈值前不告警、阈值后只发一次(持续故障不刷屏)、探测抛错按不可用且错误进正文、恢复需连续成功且中途抖动会归零、通知/管理员列表失败都不抛错
  • tests/integration/storage-watch-admins.test.ts 1 例(真实 DB):有效管理员在列,过期成员与非管理员都不在。反向验证:去掉 expiresAt 过滤后该用例转红并指出过期管理员被算进收件人
  • jobs-contract.test.ts 清单加 storage.watch 5min(改名/改频率即红),并断言 deps 缺失时完全不注册(零出网)
  • apps/api 单元测试全跑:98 文件 / 913 例通过;tsc 干净

对标 #12.5 里「4 项缺失」的最后一项:对方 `ossExceptionNotice()` 每 5 分钟探一次
对象存储,失败就通知管理员;我方 `/ready` 有存储探测,但探测结果只对探针可见,
存储挂了没人收到通知。

## 不照抄对方的两处

1. **抖一下就通知** → 协议是「连续 3 次失败才告警」(5 分钟一次 ≈ 15 分钟延迟)。
   一次超时可能只是网络抖动,而管理员会被无意义告警训练成「不看了」。
2. **只报故障不报恢复** → 恢复也要「连续 2 次成功」才发,避免故障/恢复交替刷屏,
   同时让管理员知道要不要继续排查。

## 实现

- 新内核任务 `storage.watch`(5 分钟,与对方同频),`createStorageWatch()` 持有
  `failures/successes/alerted` 三个计数;探测抛错按不可用处理,**不向任务抛出**
  (否则任务进死信被反复重试)。
- 收件人用 `listAdminUserIds()`:管理员在数据模型里不是 `User` 字段,而是权限组
  授予的 `platform.admin`;限时成员按读路径规则过滤过期行 —— 与 `hasPermission`
  同一口径,否则过期的管理员权益会让告警一直发给无权的人。
- 新增通知类型 `admin.storage.unreachable` / `admin.storage.recovered` 并登记在内建
  目录(「发出即声明」守门覆盖)。类型字面量写在 `type:` 位置而不是用模板串拼,
  否则会绕过 `notification-type-coverage` 扫描。

## 验证

- `tests/unit/storage-watch.test.ts` 5 例:阈值前不告警、阈值后只发一次(持续故障
  不刷屏)、探测抛错按不可用且错误进正文、恢复需连续成功且中途抖动会归零、
  通知/管理员列表失败都不抛错。
- `tests/integration/storage-watch-admins.test.ts` 1 例(真实 DB):有效管理员在列,
  **过期成员与非管理员都不在**。反向验证:去掉 `expiresAt` 过滤后该用例转红并指出
  过期管理员被算进收件人。
- `jobs-contract.test.ts` 清单加 `storage.watch` 5min(改名/改频率即红),
  并断言 deps 缺失时**完全不注册**(零出网)。
- `apps/api` 单元测试全跑:98 文件 / 913 例通过;`tsc` 干净。
@worable233
worable233 merged commit 0b25088 into main Oct 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant