feat(admin): Implement System Knowledge Base management module
Features:
- Backend: SystemKbService with full CRUD (knowledge bases + documents)
- Backend: 8 RESTful API endpoints (list/detail/create/update/delete/upload/download)
- Backend: OSS storage integration (system/knowledge-bases/{kbId}/{docId})
- Backend: RAG engine integration (document parsing, chunking, vectorization)
- Frontend: SystemKbListPage with card-based layout
- Frontend: SystemKbDetailPage with document management table
- Frontend: Master-Detail UX pattern for better user experience
- Document upload (single/batch), download (preserving original filename), delete
Technical:
- Database migration for system_knowledge_bases and system_kb_documents tables
- OSSAdapter.getSignedUrl with Content-Disposition for original filename
- Reuse RAG engine from common/rag for document processing
Tested: Local environment verified, all features working
This commit is contained in:
@@ -1,21 +1,22 @@
|
||||
# AIclinicalresearch 系统当前状态与开发指南
|
||||
|
||||
> **文档版本:** v4.3
|
||||
> **文档版本:** v4.4
|
||||
> **创建日期:** 2025-11-28
|
||||
> **维护者:** 开发团队
|
||||
> **最后更新:** 2026-01-25
|
||||
> **最后更新:** 2026-01-27
|
||||
> **🎉 重大里程碑:**
|
||||
> - **2026-01-27:系统知识库管理功能完成!** 运营管理端新增知识库管理+文档上传下载
|
||||
> - **2026-01-25:Protocol Agent MVP完整交付!** 一键生成研究方案+Word导出
|
||||
> - **2026-01-24:Protocol Agent 框架完成!** 可复用Agent框架+5阶段对话流程
|
||||
> - **2026-01-22:OSS 存储集成完成!** 阿里云 OSS 正式接入平台基础层
|
||||
> - **2026-01-21:成功替换 Dify!** PKB 模块完全使用自研 pgvector RAG 引擎
|
||||
>
|
||||
> **最新进展(Protocol Agent MVP 完整交付 2026-01-25):**
|
||||
> - ✅ **一键生成研究方案**:流式输出+A4预览+12章节结构
|
||||
> - ✅ **Word文档导出**:Pandoc转换,格式完美
|
||||
> - ✅ **动态双面板布局**:可拖拽调整,收集65:35/生成35:65
|
||||
> - ✅ **用户体验优化**:折叠展开、延迟创建、滚动跟随
|
||||
> - ✅ **代码总量**:~8,500行(前端3,300+后端4,700+Python500)
|
||||
> **最新进展(系统知识库管理 2026-01-27):**
|
||||
> - ✅ **系统知识库管理**:运营管理端新增知识库模块,支持 Prompt 引用
|
||||
> - ✅ **主从页面模式**:Master-Detail UX,卡片列表+文档管理表格
|
||||
> - ✅ **文档管理**:上传(单个/批量)、下载(保留原始文件名)、删除
|
||||
> - ✅ **RAG 引擎集成**:文档解析、分块、向量化存储
|
||||
> - ✅ **OSS 存储集成**:system/knowledge-bases/{kbId}/{docId} 路径
|
||||
>
|
||||
> **部署状态:** ✅ 生产环境运行中 | 公网地址:http://8.140.53.236/
|
||||
> **文档目的:** 快速了解系统当前状态,为新AI助手提供上下文
|
||||
@@ -58,7 +59,7 @@
|
||||
| **SSA** | 智能统计分析 | 队列/预测模型/RCT分析 | ⭐⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程、Word导出 | ⭐⭐⭐⭐ | ✅ **开发完成(95%)** | P3 |
|
||||
| **ADMIN** | 运营管理端 | Prompt管理、租户管理、用户管理、运营监控 | ⭐⭐⭐⭐⭐ | 🎉 **Phase 4.2完成(80%)** - 运营监控MVP+登录优化 | **P0** |
|
||||
| **ADMIN** | 运营管理端 | Prompt管理、租户管理、用户管理、运营监控、系统知识库 | ⭐⭐⭐⭐⭐ | 🎉 **Phase 4.5完成(85%)** - 系统知识库管理+文档上传下载 | **P0** |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ADMIN-运营管理端 - 模块当前状态与开发指南
|
||||
|
||||
> **最后更新:** 2026-01-25
|
||||
> **状态:** ✅ Phase 4.2 运营监控系统MVP完成!登录跳转逻辑优化完成!
|
||||
> **版本:** v0.6 (Alpha)
|
||||
> **最后更新:** 2026-01-27
|
||||
> **状态:** ✅ Phase 4.5 系统知识库管理功能完成!
|
||||
> **版本:** v0.7 (Alpha)
|
||||
|
||||
---
|
||||
|
||||
@@ -113,6 +113,16 @@
|
||||
- [x] 修复:PKB 工作区问答页面布局问题(CSS类名冲突)
|
||||
- [x] 修复:Protocol Agent 模块 CSS 类名重命名(.pa-chat-container)
|
||||
|
||||
**Phase 4.5:系统知识库管理** ✅ 已完成(2026-01-27)🎉
|
||||
- [x] 后端:SystemKbService 完整 CRUD(知识库+文档)
|
||||
- [x] 后端:8个 RESTful API 接口(列表/详情/创建/更新/删除/上传/下载)
|
||||
- [x] 后端:OSS 存储集成(system/knowledge-bases/{kbId}/{docId})
|
||||
- [x] 后端:RAG 引擎集成(文档解析、分块、向量化)
|
||||
- [x] 前端:SystemKbListPage 主页面(卡片式布局)
|
||||
- [x] 前端:SystemKbDetailPage 详情页(文档管理表格)
|
||||
- [x] 前端:主从页面模式(Master-Detail UX)
|
||||
- [x] 功能:文档上传(单个/批量)、下载(保留原始文件名)、删除
|
||||
|
||||
### ⏳ 待开发(按优先级)
|
||||
|
||||
**P2 - 用户管理增强(可选)**
|
||||
|
||||
146
docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-27_系统知识库管理功能完成.md
Normal file
146
docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-27_系统知识库管理功能完成.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# 2026-01-27 系统知识库管理功能完成
|
||||
|
||||
> **开发日期:** 2026-01-27
|
||||
> **开发者:** AI Assistant
|
||||
> **状态:** ✅ 功能完整可用
|
||||
|
||||
---
|
||||
|
||||
## 📋 开发内容
|
||||
|
||||
### 系统知识库管理功能(System KB)
|
||||
|
||||
运营管理端新增「系统知识库」模块,供管理员创建和管理公共知识库,支持 Prompt 引用。
|
||||
|
||||
---
|
||||
|
||||
## ✅ 已完成功能
|
||||
|
||||
### 1. 后端 API(8 个接口)
|
||||
|
||||
| 接口 | 方法 | 路径 | 功能 |
|
||||
|------|------|------|------|
|
||||
| 知识库列表 | GET | `/api/v1/admin/system-kb` | 获取所有系统知识库 |
|
||||
| 知识库详情 | GET | `/api/v1/admin/system-kb/:id` | 获取单个知识库详情 |
|
||||
| 创建知识库 | POST | `/api/v1/admin/system-kb` | 创建新知识库 |
|
||||
| 更新知识库 | PATCH | `/api/v1/admin/system-kb/:id` | 更新知识库信息 |
|
||||
| 删除知识库 | DELETE | `/api/v1/admin/system-kb/:id` | 删除知识库(含所有文档) |
|
||||
| 文档列表 | GET | `/api/v1/admin/system-kb/:id/documents` | 获取知识库文档列表 |
|
||||
| 上传文档 | POST | `/api/v1/admin/system-kb/:id/documents` | 上传文档(支持 PDF/Word/TXT) |
|
||||
| 删除文档 | DELETE | `/api/v1/admin/system-kb/:id/documents/:docId` | 删除单个文档 |
|
||||
| 下载文档 | GET | `/api/v1/admin/system-kb/:id/documents/:docId/download` | 获取文档下载链接 |
|
||||
|
||||
**后端文件:**
|
||||
- `backend/src/modules/admin/system-kb/systemKbService.ts` - 核心业务逻辑
|
||||
- `backend/src/modules/admin/system-kb/systemKbController.ts` - 请求处理
|
||||
- `backend/src/modules/admin/system-kb/systemKbRoutes.ts` - 路由定义
|
||||
- `backend/src/modules/admin/system-kb/index.ts` - 模块导出
|
||||
|
||||
### 2. 前端界面(主从页面模式)
|
||||
|
||||
**Master 页面 - 知识库列表**
|
||||
- 卡片式布局展示所有知识库
|
||||
- 显示知识库名称、代码、文档数、Token 数
|
||||
- 支持创建新知识库(Modal 弹窗)
|
||||
- 支持编辑、删除知识库
|
||||
- 点击卡片进入详情页
|
||||
|
||||
**Detail 页面 - 知识库详情**
|
||||
- 顶部:面包屑导航 + 返回按钮
|
||||
- 统计卡片:文档数、Token 总量
|
||||
- 文档表格:文件名、大小、Token、状态、上传时间、操作
|
||||
- 支持单个/批量上传文档
|
||||
- 支持单个/批量删除文档
|
||||
- 上传进度显示
|
||||
- 下载文档功能(保留原始文件名)
|
||||
|
||||
**前端文件:**
|
||||
- `frontend-v2/src/modules/admin/pages/SystemKbListPage.tsx` - 列表页
|
||||
- `frontend-v2/src/modules/admin/pages/SystemKbDetailPage.tsx` - 详情页
|
||||
- `frontend-v2/src/modules/admin/api/systemKbApi.ts` - API 调用
|
||||
- `frontend-v2/src/modules/admin/types/systemKb.ts` - 类型定义
|
||||
|
||||
### 3. 数据库设计
|
||||
|
||||
**表结构:**
|
||||
- `capability_schema.system_knowledge_bases` - 系统知识库表
|
||||
- `capability_schema.system_kb_documents` - 知识库文档表
|
||||
- `ekb_schema.ekb_knowledge_base` - EKB 知识库(RAG 引擎)
|
||||
- `ekb_schema.ekb_document` - EKB 文档(向量化)
|
||||
- `ekb_schema.ekb_chunk` - 文档分块(向量存储)
|
||||
|
||||
### 4. OSS 存储集成
|
||||
|
||||
**存储路径:** `system/knowledge-bases/{kbId}/{docId}.{ext}`
|
||||
|
||||
**遵循规范:**
|
||||
- ✅ UUID 命名存储,原始文件名存数据库
|
||||
- ✅ 签名 URL 下载,支持 Content-Disposition
|
||||
- ✅ 下载时恢复原始文件名
|
||||
|
||||
### 5. RAG 引擎集成
|
||||
|
||||
复用 `common/rag/` RAG 引擎能力:
|
||||
- DocumentIngestService:文档解析、分块、向量化
|
||||
- EmbeddingService:文本向量化(text-embedding-v4)
|
||||
- 存储到 pgvector 向量数据库
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术要点
|
||||
|
||||
### 下载功能实现
|
||||
|
||||
```typescript
|
||||
// 使用 OSSAdapter.getSignedUrl 传入原始文件名
|
||||
const ossAdapter = storage as OSSAdapter;
|
||||
const url = ossAdapter.getSignedUrl(doc.file_path, 3600, doc.filename);
|
||||
// 生成的 URL 带有 Content-Disposition 头,浏览器下载时使用原始文件名
|
||||
```
|
||||
|
||||
### 主从页面路由
|
||||
|
||||
```typescript
|
||||
// App.tsx 路由配置
|
||||
<Route path="system-kb" element={<SystemKbListPage />} />
|
||||
<Route path="system-kb/:id" element={<SystemKbDetailPage />} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 代码量统计
|
||||
|
||||
| 文件类型 | 文件数 | 代码行数(约) |
|
||||
|---------|--------|---------------|
|
||||
| 后端 Service | 1 | ~500 行 |
|
||||
| 后端 Controller | 1 | ~340 行 |
|
||||
| 后端 Routes | 1 | ~75 行 |
|
||||
| 前端 ListPage | 1 | ~320 行 |
|
||||
| 前端 DetailPage | 1 | ~450 行 |
|
||||
| 前端 API | 1 | ~130 行 |
|
||||
| 前端 Types | 1 | ~60 行 |
|
||||
| **合计** | **7** | **~1,875 行** |
|
||||
|
||||
---
|
||||
|
||||
## 📝 下一步计划
|
||||
|
||||
1. **Prompt + 知识库关联**
|
||||
- 在 Prompt 编辑页添加知识库选择器
|
||||
- 实现 Prompt 调用时自动 RAG 检索
|
||||
|
||||
2. **知识库搜索**
|
||||
- 添加知识库内全文检索功能
|
||||
- 语义搜索测试界面
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- 开发计划:`docs/03-业务模块/ADMIN-运营管理端/04-开发计划/05-Prompt知识库集成开发计划.md`
|
||||
- OSS 规范:`docs/04-开发规范/11-OSS存储开发规范.md`
|
||||
- RAG 引擎:`docs/02-通用能力层/03-RAG引擎/05-RAG引擎使用指南.md`
|
||||
|
||||
---
|
||||
|
||||
*开发记录完成*
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,77 +0,0 @@
|
||||
# 测试文档
|
||||
|
||||
> **文档定位:** 测试策略、测试用例、测试报告
|
||||
> **适用范围:** 开发团队、QA团队
|
||||
|
||||
---
|
||||
|
||||
## 📋 测试策略
|
||||
|
||||
### 1. 单元测试
|
||||
- 核心业务逻辑测试
|
||||
- 工具函数测试
|
||||
- 覆盖率目标:60%+
|
||||
|
||||
### 2. 集成测试
|
||||
- API端点测试
|
||||
- 数据库集成测试
|
||||
- 外部服务集成测试
|
||||
|
||||
### 3. 端到端测试
|
||||
- 关键业务流程测试
|
||||
- UI自动化测试
|
||||
|
||||
### 4. 性能测试
|
||||
- API响应时间
|
||||
- 并发测试
|
||||
- 压力测试
|
||||
|
||||
---
|
||||
|
||||
## 📚 测试文档清单
|
||||
|
||||
| 文档 | 说明 | 状态 |
|
||||
|------|------|------|
|
||||
| **01-测试策略.md** | 整体测试策略和方法 | ⏳ 待创建 |
|
||||
| **02-自动化测试.md** | 自动化测试框架和实践 | ⏳ 待创建 |
|
||||
| **03-性能测试.md** | 性能测试标准和工具 | ⏳ 待创建 |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 各模块测试文档
|
||||
|
||||
每个业务模块的测试文档在各自的目录下:
|
||||
- `03-业务模块/ASL-AI智能文献/04-测试文档/`
|
||||
- `03-业务模块/AIA-AI智能问答/04-测试文档/`
|
||||
- ...
|
||||
|
||||
---
|
||||
|
||||
**最后更新:** 2025-11-06
|
||||
**维护人:** 技术架构师
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
# **PG Boss 任务重复故障分析与修复方案**
|
||||
|
||||
## **1\. 故障核心分析 (Root Cause Analysis) \- 修正版**
|
||||
|
||||
针对 "同一 TaskID 被创建 7 次" 且 "创建时间在同一毫秒" 的现象,在确认 **仅有 1 个 SAE 实例** 运行的情况下,我们排除了多实例并发的可能性。
|
||||
|
||||
结合已清理的 "rvw\_review\_task 有 7 个重复条目" 这一关键证据,我们得出了确切的结论:
|
||||
|
||||
### **核心根因:持久化配置重复 (Persisted Configuration Duplication)**
|
||||
|
||||
**问题不在于有多少个实例在跑,而在于数据库里存了多少份重复的指令。**
|
||||
|
||||
#### **💡 深度解析:为什么会有 7 个?(7 个闹钟的比喻)**
|
||||
|
||||
你的疑问是:*"每次处理应该是生成不同的任务ID,不可能是重复的对吗?"*
|
||||
|
||||
**答案:是的,pg-boss 生成了 7 个完全不同的 Job ID,但它们都在做同一件事。**
|
||||
|
||||
这就好比你为了早上 7 点起床,设置了 **7 个闹钟**:
|
||||
|
||||
1. **指令 (Schedules/Definitions)**:数据库里那些被清理的 "7 个重复条目",就像是 7 个闹钟配置。它们都设定在同一个触发条件下(比如 Cron 表达式,或系统启动时)。
|
||||
2. **触发 (Trigger)**:当时间到了,或者系统启动扫描时,这 **7 个闹钟同时响了**。
|
||||
3. **执行 (Jobs)**:系统听到第 1 个闹钟,创建了 Job A;听到第 2 个闹钟,创建了 Job B... 直到 Job G。
|
||||
* **结果**:你在一毫秒内,被叫醒了 7 次。
|
||||
* **数据**:这 7 个 Job 都有**不同的 UUID**(符合数据库约束),但它们的\*\*内容(Payload)\*\*全是 "处理 Task bd19c3d3"。
|
||||
|
||||
这就是为什么你在数据库里看到 created\_on 完全一致,但 Job ID 不同。因为那 1 个 SAE 实例在极短的时间内,忠实地执行了数据库里残留的 7 条指令。
|
||||
|
||||
* **机制解析**:pg-boss 是一个基于数据库的任务队列。它的调度(Schedules)和某些队列配置是**持久化**在 PostgreSQL 数据库中的(通常在 pgboss.schedule 表中)。
|
||||
* **故障复盘**:
|
||||
1. **积累阶段**:在过去的历史部署或重启中,代码可能在启动时调用了 boss.schedule('queue', 'cron')。由于没有加去重逻辑,每次部署都在数据库里**新增**了一条调度记录,而不是更新旧的。日积月累,数据库里就有了 7 条完全一样的调度记录。
|
||||
2. **爆发阶段**:当你当前的 **1 个 SAE 实例** 运行时,pg-boss 内部的轮询器扫描数据库,读取到了这 7 条重复的记录。
|
||||
3. **瞬间执行**:当触发条件满足,这单个实例在极短的 CPU 周期内,为这 7 条记录分别生成了一个 Job。
|
||||
* **证据链闭环**:
|
||||
* **7 次重复** 对应 **7 个重复的 Schedule/配置记录**。
|
||||
* **同一毫秒创建** 对应 **单实例在一次事件循环中连续处理了这 7 条指令**。
|
||||
|
||||
**结论**:你执行的 "清理了 32 个重复的队列定义" 操作,实际上就是**关掉了多余的 6 个闹钟**,这已经移除了问题的根源。
|
||||
|
||||
### **为什么 SingletonKey 之前没生效?**
|
||||
|
||||
虽然这是单实例产生的重复,但如果代码使用的是 insert 或者是没有严格 unique constraint 保护的 send,在极快的循环中(Event Loop),数据库可能仍未完成第一条的提交,第二条就来了。
|
||||
|
||||
但最可能的原因是:**生成 Key 的逻辑有问题**,或者根本没有在产生任务的那段特定逻辑中加上 singletonKey。
|
||||
|
||||
## **2\. 解决方案:三层防御体系**
|
||||
|
||||
虽然根因(重复配置)已被你清理,但为了防止未来代码逻辑再次意外引入重复配置,或者防止前端意外的连击,我们依然强烈建议保留以下防御措施。
|
||||
|
||||
### **第一层:入队时防御 (生产者层面 \- 强制去重)**
|
||||
|
||||
这是最关键的一步。无论是因为配置重复导致被调用 7 次,还是前端点了 7 次,这里都能拦住。
|
||||
|
||||
**修改代码建议 (Producer/Service):**
|
||||
|
||||
// reviewTaskProducer.ts
|
||||
|
||||
import { PgBoss } from 'pg-boss';
|
||||
|
||||
// 假设这是你的入队逻辑
|
||||
export async function createReviewTask(boss: PgBoss, taskId: string, payload: any) {
|
||||
const queueName \= 'rvw\_review\_task';
|
||||
|
||||
// ✅ 核心修复:构造确定性的 singletonKey
|
||||
// 不要包含时间戳等变量,只包含业务唯一标识 (如 taskId)
|
||||
const singletonKey \= \`review\_task\_${taskId}\`;
|
||||
|
||||
// 发送任务
|
||||
const jobId \= await boss.send(queueName, payload, {
|
||||
// ✅ 启用单例模式
|
||||
singletonKey: singletonKey,
|
||||
// ✅ 节流/防抖:如果任务已存在且活跃,300秒内不再创建
|
||||
singletonSeconds: 300,
|
||||
// ✅ 即使旧任务完成了,保留Key一段时间以防重复触发
|
||||
singletonNextSlot: false
|
||||
});
|
||||
|
||||
if (\!jobId) {
|
||||
console.warn(\`\[Duplicate Prevented\] Task ${taskId} already exists in queue.\`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return jobId;
|
||||
}
|
||||
|
||||
### **第二层:处理时防御 (Worker 层面 \- 幂等性检查)**
|
||||
|
||||
你已经添加了状态检查,这很好。为了处理潜在的竞争(虽然单实例下竞争少,但为了健壮性),建议保持乐观锁逻辑。
|
||||
|
||||
**修改代码建议 (Worker):**
|
||||
|
||||
// reviewWorker.ts
|
||||
|
||||
export async function processReviewTask(job: Job) {
|
||||
const { taskId } \= job.data;
|
||||
|
||||
// 1\. 业务状态检查 (你已经做了)
|
||||
const task \= await db.task.findUnique({ where: { id: taskId } });
|
||||
|
||||
// ✅ 状态检查:如果已经是处理中或完成,直接跳过
|
||||
if (task.status \=== 'COMPLETED' || task.status \=== 'PROCESSING') {
|
||||
console.log(\`\[Skipped\] Task ${taskId} is already ${task.status}\`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2\. 乐观锁更新 (Database Atomic Update)
|
||||
const updateResult \= await db.task.updateMany({
|
||||
where: {
|
||||
id: taskId,
|
||||
status: 'PENDING' // 👈 关键:只有当前状态是 PENDING 时才更新
|
||||
},
|
||||
data: {
|
||||
status: 'PROCESSING',
|
||||
startedAt: new Date()
|
||||
}
|
||||
});
|
||||
|
||||
if (updateResult.count \=== 0\) {
|
||||
console.log(\`\[Concurrency Control\] Task ${taskId} claimed by another worker or logic.\`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3\. 执行逻辑
|
||||
try {
|
||||
await performReviewLogic(taskId);
|
||||
await db.task.update({ where: { id: taskId }, data: { status: 'COMPLETED' }});
|
||||
} catch (error) {
|
||||
await db.task.update({ where: { id: taskId }, data: { status: 'FAILED' }});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
### **第三层:初始化代码审查 (防止复发)**
|
||||
|
||||
针对 **"32 个重复队列定义"** 的来源,需要检查你的启动代码。
|
||||
|
||||
1. **检查 schedule 调用**:
|
||||
如果你在代码里使用了 boss.schedule('queue', cron, ...),请确保不要在每次应用启动时都无脑调用。
|
||||
* **错误做法**:在 main.ts 直接调用 boss.schedule(...)。每次部署都会尝试再加一个(取决于 pg-boss 版本行为)。
|
||||
* **正确做法**:通常 pg-boss 会处理去重,但如果参数稍有不同(比如 cron 表达式或数据),它可能会视为新 Schedules。建议检查 pg-boss 的 schedules 表,确保没有垃圾数据。
|
||||
2. **清理脚本**:
|
||||
保留一个数据库迁移脚本或运维 SQL,定期检查 pg-boss 的 job 表中是否有异常激增的 created 状态的任务。
|
||||
|
||||
## **3\. 总结**
|
||||
|
||||
* **问题原因**:数据库中残留的历史重复配置(7个重复条目)导致单实例在循环中瞬间创建了 7 个任务。
|
||||
* **当前状态**:你清理了重复条目,这已经解决了根源。
|
||||
* **未来保障**:部署带有 singletonKey 的代码,这将是永远的防线,即使数据库里有 100 个重复配置,pg-boss 也会拒绝创建第 2 到 第 100 个任务。
|
||||
Reference in New Issue
Block a user