merge: 集成V2.6 性能增强与小宝后台化
# Conflicts: # apps/server/prisma/schema.prisma # apps/server/src/app.module.ts # apps/web/components/layout/Sidebar.tsx # docs/architecture.md # docs/decisions.md # docs/roadmap.md
This commit is contained in:
@@ -157,6 +157,27 @@ V2.5 控制面新增三类横切能力:
|
||||
- V2.6 在关系表主源稳定后做大数据性能增强和小宝预警后台化;性能基础不后置,增强项包括压测、慢查询治理、缓存/摘要、后台任务、幂等和失败重试。
|
||||
- V2.7 面向企业级协作与管理治理,V2.8 面向生产硬化与运维闭环;生产部署基线已经存在,V2.8 重点是备份恢复演练、发布 smoke test、监控告警、日志检索、迁移回滚和运维手册。
|
||||
|
||||
## Background Job Runtime Layer (V2.6)
|
||||
|
||||
V2.6 introduces a database-backed background job runtime for server-side refresh work that must not depend on a user opening a page.
|
||||
|
||||
- Storage: `background_jobs` stores `type`, `payload`, `dedupe_key`, `status`, `attempts`, `max_attempts`, `available_at`, `locked_by`, `locked_until`, and `last_error`.
|
||||
- Dedupe: active jobs (`queued` / `running`) are unique by `(type, dedupe_key)` when `dedupe_key` is present. Services still check first and recover from unique conflicts to stay idempotent under concurrent enqueue.
|
||||
- Lease: `JobLockService.claimNext()` uses `FOR UPDATE SKIP LOCKED` and treats expired `running` rows as claimable, so a crashed worker can be recovered by a later worker.
|
||||
- Retry: failed handlers are requeued while `attempts < max_attempts`; terminal failures keep `last_error` and move to `failed`.
|
||||
- Worker boundary: `BackgroundJobWorker` is a small handler registry and single-job runner. Domain modules register typed handlers and only write through their own services.
|
||||
|
||||
This runtime is intentionally DB-backed first. Redis is already available in deployment, but V2.6 jobs need transactional dedupe with domain writes more than high-throughput queue semantics.
|
||||
|
||||
## Runtime Ops Dashboard (V2.6)
|
||||
|
||||
V2.6 adds an Ops runtime surface for local operators and future production admins:
|
||||
|
||||
- Backend: `OpsModule` exposes `GET /api/v1/ops/runtime`, reading recent in-memory slow API request events, recent in-memory slow Prisma query events, `background_jobs` queue rows, and dirty `xiaobao_risk_summaries` count.
|
||||
- Capture: `ApiTimingInterceptor` and `PrismaService` still log slow events, and also append redacted bounded previews into the Ops runtime buffer. SQL query parameters are not exposed; request query strings and key-like values are stripped or redacted.
|
||||
- Jobs: the dashboard summarizes queued/running/succeeded/failed jobs by type and shows recent terminal failures with redacted `lastError`.
|
||||
- Permissions: the frontend route is guarded by `ops:view`. Backend RBAC is represented by `OpsPermissionAdapter` until the V2.5 RBAC contract lands, so the replacement point is explicit instead of hard-coupled to temporary role data.
|
||||
|
||||
## 生产部署层(2026-07-01)
|
||||
|
||||
当前仓库已补齐云服务器生产部署基线:
|
||||
@@ -260,7 +281,16 @@ The rule surface stays in pure frontend engines:
|
||||
|
||||
Managers with `xiaobao.warning:manage` can see all unfinished versions. Non-managers with `xiaobao.warning:view` can only see unfinished versions where the current user is in `version.members`.
|
||||
|
||||
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened. The first version uses page-triggered analysis rather than a background scheduled Agent.
|
||||
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened.
|
||||
|
||||
V2.6 moves the current risk summary refresh to the server:
|
||||
|
||||
- `XiaobaoRiskService.refreshSummary(versionId)` recomputes deterministic rule output from Version, DevTask, TestCase, Bug, WorkActivity, and TaskWorklog relation rows, then upserts `xiaobao_risk_summaries` with `dirty=false`.
|
||||
- `XiaobaoRiskWorker` registers the `xiaobao.summary.refresh` background job handler, so dirty summaries can be refreshed without opening `/xiaobao-warning`.
|
||||
- Domain writes that produce work activity already mark the affected version dirty; V2.6 also enqueues a deduped refresh job. Plain update/delete paths for version plans, dev tasks, test cases, and bugs explicitly mark the version dirty as well.
|
||||
- `XiaobaoAiService` evaluates the refreshed summary and enqueues `xiaobao.ai.interpret` when policy allows. The worker reloads the latest summary, skips stale signatures, calls the existing `AiService.interpretRisk()` prompt path, and writes only `xiaobao_risk_insights`.
|
||||
- AI interpretation cache uses the summary `riskSignature`, exact cache reuse, a six-hour cooldown, and risk-level escalation bypass. Until the server has full daily trend snapshots, `attention` summaries trigger server-side AI only when release is within one day and unfinished work remains.
|
||||
- Frontend `/xiaobao-warning` still consumes V2.2 summary reads first and only falls back to AppData calculation when summaries are empty or unavailable.
|
||||
|
||||
Per-user warning read state is saved to `xiaobao-warning-views`. The read marker stores `userId + versionId + risk signature`, so the sidebar can turn the Xiaobao badge blue when any visible risk has a completed unread update, then return to the red risk-count badge after the user opens every updated warning. AI interpretation that is still generating only shows the "updating" notice and must not produce the blue update badge yet.
|
||||
## V2.2 Partitioned Domain Data Layer (2026-07-03)
|
||||
|
||||
Reference in New Issue
Block a user