feat(media): A6 任务中心 API、SSE 进度与队列骨架
ci / 质量门禁 (push) Successful in 6m4s

背景:A6-BE-01..05 与 A6-INF-01,打通「提交 → 队列 → SSE 进度 → 完成/失败 → 取消 / 仅重试失败项」闭环,为 B3 / M1 的真实任务提供统一协议。
改动:
- API media 模块:POST/GET /media-tasks、详情、SSE(Last-Event-ID 续推 + 15s 心跳 + 800ms 落库轮询)、取消(只影响未开始项)、仅重试失败项;Idempotency-Key 24h(异步提交 202;同 key 同 body 返回同一任务且不重复审计,不同 body 40902);范围外统一 404;
- 队列骨架:BullMQ 5 九队列(5 组独立启停)、Outbox dispatcher(Redis 锁 + FOR UPDATE SKIP LOCKED + jobId 幂等 + 指数退避/死信)、worker 按 QUEUE 启停、demo 演练处理器(事务 + 行锁 + 取消/重试/幂等)、优雅退出与心跳;
- 监控:GET /api/v1/health/queues、GET /api/v1/metrics(Prometheus 0.0.4)、infra/monitoring 告警规则与接入说明;
- 通用:AuditInterceptor 支持幂等重放 skipAudit(默认行为不变)、AppModule 接线、.env.example 的 QUEUE 语义、bullmq 5.81.5 / worker @prisma/client / worker 覆盖率依赖。
影响面:OpenAPI 新增 6 个端点(openapi:diff 无破坏性变更);API 进程新增 outbox dispatcher 与 metrics/health 路由;worker 新增 BullMQ 消费;未改旧审计导出链路与既有接口。
回滚:回滚提交并停止 worker 新队列消费;task/outbox 新表数据不影响旧功能,可按需保留。
验证:api 单测 257、集成 92(连跑 2 次)、worker 27、shared 197;typecheck / lint / format:check / build / openapi:diff 全绿;本地真实 worker 启用 9 队列心跳,/health/queues、/metrics 实测,/media-tasks 未登录 401。
This commit is contained in:
Stev_Wang committed 2026-11-04 21:52:35 +08:00
1 parent 4a29cf815e
commit 633765f10f
70 files changed
+8674 -45

No files matched your search

+52
View File
@@ -0,0 +1,52 @@
# 灵犀 · 队列监控告警规则(A6-INF-01)
# 指标来源:API 的 Prometheus 端点 GET /api/v1/metrics(text/plain; version=0.0.4)
# 指标定义:lingxi_queue_jobs / lingxi_queue_oldest_waiting_seconds / lingxi_queue_failure_ratio /
# lingxi_worker_heartbeat_age_seconds / lingxi_outbox_pending_total / lingxi_outbox_dead_letter_total
#
# 加载方式见同目录 README.md;阈值调整需走配置评审(R-26 精神:阈值集中管理)。
groups:
- name: lingxi-queue
rules:
# 队列积压:队首任务等待超过 10 分钟
- alert: LingxiQueueBacklog
expr: lingxi_queue_oldest_waiting_seconds > 600
for: 5m
labels:
severity: warning
component: queue
annotations:
summary: '队列 {{ $labels.queue }} 积压'
description: '队列 {{ $labels.queue }} 队首任务已等待 {{ $value | humanizeDuration }}(阈值 600s,持续 5m);请检查 worker 是否在跑、并发是否被占满。'
# 失败率:failed/(failed+completed) 超过 5%
- alert: LingxiQueueHighFailureRatio
expr: lingxi_queue_failure_ratio > 0.05
for: 10m
labels:
severity: warning
component: queue
annotations:
summary: '队列 {{ $labels.queue }} 失败率偏高'
description: '队列 {{ $labels.queue }} 失败率 {{ $value | humanizePercentage }}(阈值 5%,持续 10m);请查看失败 job 与 worker 日志。'
# worker 心跳缺失(-1)或超过 60s 未续写
- alert: LingxiWorkerHeartbeatMissing
expr: lingxi_worker_heartbeat_age_seconds < 0 or lingxi_worker_heartbeat_age_seconds > 60
for: 2m
labels:
severity: critical
component: worker
annotations:
summary: '队列 {{ $labels.queue }} 的 worker 心跳缺失'
description: '队列 {{ $labels.queue }} 心跳年龄 {{ $value }}s(缺失为 -1,阈值为 60s,持续 2m);worker 可能已退出或 Redis 不可用。'
# outbox 死信:出现即需要人工介入(避免事件永久卡住)
- alert: LingxiOutboxDeadLetter
expr: lingxi_outbox_dead_letter_total > 0
for: 1m
labels:
severity: critical
component: outbox
annotations:
summary: 'Outbox 出现死信事件'
description: '累计死信 {{ $value }} 条(outbox_events.last_error=dead_lettered);请核对 payload 与目标队列配置后人工补投。'