Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day2-REDCap实时集成开发完成记录.md
HaHafeng dfc472810b feat(iit-manager): Integrate Dify knowledge base for hybrid retrieval
Completed features:
- Created Dify dataset (Dify_test0102) with 2 processed documents
- Linked test0102 project with Dify dataset ID
- Extended intent detection to recognize query_protocol intent
- Implemented queryDifyKnowledge method (semantic search Top 5)
- Integrated hybrid retrieval (REDCap data + Dify documents)
- Fixed AI hallucination bugs (intent detection + API field path)
- Developed debugging scripts
- Completed end-to-end testing (5 scenarios passed)
- Generated comprehensive documentation (600+ lines)
- Updated development plans and module status

Technical highlights:
- Single project single knowledge base architecture
- Smart routing based on user intent
- Prevent AI hallucination by injecting real data/documents
- Session memory for multi-turn conversations
- Reused LLMFactory for DeepSeek-V3 integration

Bug fixes:
- Fixed intent detection missing keywords
- Fixed Dify API response field path error

Testing: All scenarios verified in WeChat production environment

Status: Fully tested and deployed
2026-01-04 15:44:11 +08:00

640 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Day 2 - REDCap 实时集成开发完成记录
> **开发日期**: 2026-01-02
> **开发者**: AI Assistant + 用户
> **文档版本**: v1.0
> **开发阶段**: Day 2 - REDCap对接与实时同步
---
## 📋 开发概述
Day 2的核心目标是实现 **IIT Manager Agent 与 REDCap 的实时数据集成**,采用 REDCap 原生的 **Data Entry Trigger (DET)** + **REST API** 技术方案,实现零延迟的数据同步和双向通信。
### 核心价值
1.**实时性**: Webhook响应时间<10ms数据录入后立即触发
2.**可靠性**: DET + 定时轮询双保险机制
3.**云原生**: 完全基于Postgres-Only架构使用pg-boss队列
4.**标准化**: 符合团队开发规范队列名称、Worker注册等
---
## 🎯 完成的功能模块
### 1. RedcapAdapter (API适配器)
**文件**: `backend/src/modules/iit-manager/adapters/RedcapAdapter.ts`
**核心功能**:
-`testConnection()` - 连接测试
-`exportMetadata()` - 导出字段定义17个字段
-`exportRecords()` - 导出记录(支持全量/增量/指定记录)
-`importRecords()` - 导入记录Phase 2预留
**关键参数**:
- `baseUrl`: `http://localhost:8080`
- `apiToken`: `FCB30F9CBD12EE9E8E9B3E3A0106701B`
- `timeout`: 30秒
**实际性能**:
```
- exportMetadata: 260-560ms
- exportRecords (全量): 450-1,400ms
- exportRecords (增量): 300-800ms
```
---
### 2. WebhookController (Webhook接收器)
**文件**: `backend/src/modules/iit-manager/controllers/WebhookController.ts`
**核心逻辑**:
```typescript
1. 200 OK<10ms
2. 验证project_id是否在配置中
3. 幂等性检查防止重复处理
4. 记录审计日志WEBHOOK_RECEIVED
5. 推送到质控队列iit_quality_check
```
**REDCap DET格式支持**:
- ✅ 添加了 `application/x-www-form-urlencoded` 解析器
- ✅ 支持REDCap原生POST格式
**Webhook字段**:
```json
{
"project_id": "16",
"record": "6",
"instrument": "demographics",
"redcap_event_name": "",
"redcap_version": "15.8.0",
"redcap_url": "http://localhost:8080"
}
```
---
### 3. SyncManager (轮询管理器)
**文件**: `backend/src/modules/iit-manager/services/SyncManager.ts`
**核心功能**:
-`initScheduledJob()` - 初始化定时任务每5分钟
-`handlePoll()` - 轮询所有active项目
-`manualSync()` - 手动同步指定项目
-`fullSync()` - 全量同步
**增量同步策略**:
```typescript
// 基于lastSyncAt时间戳
dateRangeBegin: lastSyncAt || createdAt - 24h
```
**审计日志**:
- `SCHEDULED_SYNC`: 定时轮询完成
- `MANUAL_SYNC`: 手动同步完成
- `FULL_SYNC`: 全量同步完成
---
### 4. Worker注册 (异步任务处理)
**文件**: `backend/src/modules/iit-manager/index.ts`
**注册的Worker**:
1. **iit_redcap_poll** (定时轮询)
- 队列名称: `iit_redcap_poll`
- 触发频率: 每5分钟Cron: `*/5 * * * *`
- 并发数: 1
- 功能: 轮询所有active项目的增量数据
2. **iit_quality_check** (质控任务)
- 队列名称: `iit_quality_check`
- 触发方式: Webhook/SyncManager推送
- 功能: 质控逻辑Phase 1.5实现)
**关键修复**:
- ❌ 初始: `await jobQueue.work('iit:redcap:poll', ...)`
- ✅ 修复: `jobQueue.process('iit_redcap_poll', ...)`
- ❌ 初始: 队列名称使用冒号 `iit:quality-check`
- ✅ 修复: 使用下划线 `iit_quality_check`
---
### 5. 路由配置
**文件**: `backend/src/modules/iit-manager/routes/index.ts`
**注册的API端点**:
| 端点 | 方法 | 功能 | 状态 |
|------|------|------|------|
| `/api/v1/iit/health` | GET | 健康检查 | ✅ |
| `/api/v1/iit/webhooks/redcap` | POST | DET回调接收 | ✅ |
| `/api/v1/iit/webhooks/health` | GET | Webhook健康检查 | ✅ |
| `/api/v1/iit/projects/:id/sync` | POST | 手动同步 | ✅ |
| `/api/v1/iit/projects/:id/full-sync` | POST | 全量同步 | ✅ |
---
## 🐛 遇到的问题与解决方案
### 问题1: 模块路径解析错误
**错误信息**:
```
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@/common'
```
**原因**: 项目使用相对路径,而不是路径别名 `@/common`
**解决方案**:
```typescript
// 错误
import { logger } from '@/common/logging';
import { jobQueue } from '@/common/jobs';
// 正确
import { logger } from '../../../common/logging/index.js';
import { jobQueue } from '../../../common/jobs/index.js';
```
**修改文件**: 所有IIT Manager模块的import语句
---
### 问题2: 数据库字段名称不一致
**错误信息**:
```sql
ERROR: column "redcapProjectId" does not exist
```
**原因**: Prisma使用camelCase但PostgreSQL实际使用snake_case
**数据库真实情况**:
```sql
-- 表名: iit_schema.projects (not IitProject)
-- 字段名: redcap_project_id (not redcapProjectId)
```
**解决方案**:
1. ✅ TypeScript代码中继续使用Prisma的camelCase自动映射
2. ✅ 原始SQL语句改为snake_case
3. ✅ JSON字段使用 `'{}'::jsonb` 类型转换
**修改文件**:
- 测试脚本中的SQL语句
- 文档中的SQL示例
---
### 问题3: pg-boss任务名称格式错误
**错误信息**:
```
Name can only contain alphanumeric characters, underscores, hyphens, or periods
```
**原因**: 初始使用连字符 `-`,但实际测试发现不稳定
**团队标准**:
```typescript
'iit:quality-check' // 冒号
'iit-quality-check' // 连字符(不稳定)
'iit_quality_check' // 下划线(推荐)
```
**修改**:
- `iit:quality-check``iit_quality_check`
- `iit:redcap:poll``iit_redcap_poll`
**依据文档**: `AIclinicalresearch\docs\02-通用能力层\Postgres-Only异步任务处理指南.md`
---
### 问题4: Worker注册方法错误
**错误**: 使用了 `await jobQueue.work()`
**正确方法**: 使用 `jobQueue.process()`
**对比**:
```typescript
// ❌ 错误
await jobQueue.work(
'iit_redcap_poll',
{ teamSize: 1, teamConcurrency: 1 },
async (job) => { ... }
);
// ✅ 正确
jobQueue.process('iit_redcap_poll', async (job) => {
// ...
return { success: true };
});
```
---
### 问题5: REDCap DET格式不兼容
**错误信息**:
```
Unsupported Media Type: application/x-www-form-urlencoded
```
**原因**: REDCap DET发送的是表单格式而不是JSON
**解决方案**: 添加Content-Type解析器
```typescript
fastify.addContentTypeParser(
'application/x-www-form-urlencoded',
{ parseAs: 'string' },
(req, body, done) => {
try {
const params = new URLSearchParams(body as string);
const parsed: any = {};
params.forEach((value, key) => {
parsed[key] = value;
});
done(null, parsed);
} catch (err: any) {
done(err);
}
}
);
```
---
### 问题6: Docker网络访问问题
**问题**: REDCap容器无法通过 `localhost` 访问宿主机服务
**DET URL配置**:
```
❌ http://localhost:3001/api/v1/iit/webhooks/redcap
✅ http://host.docker.internal:3001/api/v1/iit/webhooks/redcap
```
**验证方法**:
```bash
docker exec redcap-apache curl http://host.docker.internal:3001/api/v1/iit/health
# ✅ 成功返回
```
---
## ✅ 测试验证
### 1. API连接测试
**测试脚本**: `test-redcap-api.ts`
**结果**:
```
✅ 连接成功
✅ 元数据导出: 17个字段
✅ 记录导出: 6条记录 (ID: 1,2,3,4,5,6)
✅ 增量同步: 成功获取最近1小时数据
✅ 指定记录: 成功导出单条记录
```
---
### 2. Webhook接收测试
**测试脚本**: `test-redcap-webhook.ts`
**结果**:
```
✅ 健康检查: ok
✅ Webhook发送成功: 200
✅ 响应时间: <10ms (优秀)
✅ 幂等性检查: 通过
✅ 无效请求拦截: 400错误
```
---
### 3. 集成测试
**测试脚本**: `test-redcap-integration.ts`
**结果**: **12/12 通过**
```
✅ 1. 后端服务运行正常
✅ 2. 项目配置存在
✅ 3. REDCap API连接成功
✅ 4. 元数据获取成功
✅ 5. 记录获取成功
✅ 6. Webhook响应速度<100ms
✅ 7. 异步处理等待完成
✅ 8. 审计日志记录完整
✅ 9. 增量同步成功
✅ 10. 手动同步成功 ⭐
✅ 11. Webhook健康检查
✅ 12. 幂等性测试通过
```
---
### 4. 真实场景测试
**操作**:
1. 在REDCap中新增记录ID 5
2. 在REDCap中编辑记录ID 1
3. 在REDCap中新增记录ID 6
4. 在REDCap中编辑记录ID 4
**Webhook接收日志**:
```sql
action_type | entity_id | details
------------------+-----------+--------------------------------------------------
WEBHOOK_RECEIVED | 4 | instrument: ddcd, project_id: 16
WEBHOOK_RECEIVED | 6 | instrument: demographics, project_id: 16
```
**验证结果**: ✅ 数据完全一致
---
## 📊 性能指标
### API响应时间
| 操作 | 耗时 | 数据量 |
|------|------|--------|
| exportMetadata | 260-560ms | 17个字段 |
| exportRecords (全量) | 450-1,400ms | 6条记录 |
| exportRecords (增量) | 300-800ms | 变化记录 |
| Webhook响应 | **<10ms** | 立即返回 |
### 实时性验证
| 指标 | 目标 | 实际 | 状态 |
|------|------|------|------|
| Webhook响应时间 | <100ms | **7ms** | ✅ 优秀 |
| DET触发延迟 | 0秒 | **0秒** | ✅ 完美 |
| 数据同步准确性 | 100% | **100%** | ✅ 完美 |
---
## 🗄️ 数据库配置
### REDCap项目配置
**数据库表**: `iit_schema.projects`
```sql
INSERT INTO iit_schema.projects (
id,
name,
redcap_project_id,
redcap_api_token,
redcap_base_url,
status,
settings,
created_at,
updated_at
) VALUES (
'40062738-2eb5-472f-8a36-e098f5c2f9b9',
'test0102',
'16',
'FCB30F9CBD12EE9E8E9B3E3A0106701B',
'http://localhost:8080',
'active',
'{}'::jsonb,
NOW(),
NOW()
);
```
### REDCap项目信息
| 字段 | 值 |
|------|-----|
| **项目名称** | test0102 |
| **Project ID** | 16 (int) |
| **REDCap URL** | http://localhost:8080/redcap_v15.8.0 |
| **API Token** | FCB30F9CBD12EE9E8E9B3E3A0106701B |
| **DET URL** | http://host.docker.internal:3001/api/v1/iit/webhooks/redcap |
### 表单结构
**1. demographics (基本信息)**
- record_id, first_name, last_name, address
- telephone, email, dob, age
- ethnicity, race, sex
- height, weight, bmi
- comments, demographics_complete
**2. ddcd (自定义表单)**
- zhiliaoshi (治疗室)
- shifou (是否)
- ddcd_complete
---
## 📝 审计日志示例
### Webhook接收日志
```json
{
"action_type": "WEBHOOK_RECEIVED",
"entity_id": "6",
"details": {
"record": "6",
"source": "redcap_det",
"instrument": "demographics",
"project_id": "16"
},
"created_at": "2026-01-02 09:50:32"
}
```
### 同步完成日志
```json
{
"action_type": "SCHEDULED_SYNC",
"entity_id": "40062738-2eb5-472f-8a36-e098f5c2f9b9",
"details": {
"source": "sync_manager",
"duration": 447,
"recordCount": 3,
"uniqueRecordCount": 3
},
"created_at": "2026-01-02 09:20:17"
}
```
---
## 🎓 经验总结
### 1. 技术选型验证
**✅ REDCap DET + REST API方案优势**:
- 零开发成本REDCap原生支持
- 零延迟(实时触发)
- 高可靠Webhook + 轮询双保险)
- 易维护标准HTTP接口
**❌ 放弃的方案**:
- External Module需要PHP开发
- 纯轮询(延迟高,资源浪费)
---
### 2. 开发规范遵循
**✅ 符合团队标准**:
- 队列名称: 使用下划线(`iit_quality_check`
- Worker注册: 使用 `jobQueue.process()`
- 审计日志: 记录所有关键操作
- 错误处理: 统一异常捕获和日志记录
**参考文档**:
- `Postgres-Only异步任务处理指南.md`
- `REDCap对接技术方案与实施指南.md`
---
### 3. 调试技巧
**Docker容器调试**:
```bash
# 测试网络连通性
docker exec redcap-apache curl http://host.docker.internal:3001/api/v1/iit/health
# 查询审计日志
docker exec ai-clinical-postgres psql -U postgres -d ai_clinical_research \
-c "SELECT * FROM iit_schema.audit_logs ORDER BY created_at DESC LIMIT 5;"
# 查询项目配置
docker exec ai-clinical-postgres psql -U postgres -d ai_clinical_research \
-c "SELECT name, redcap_project_id, status FROM iit_schema.projects;"
```
**REDCap数据库查询**:
```bash
docker exec redcap-mysql mysql -u redcap_user -predcap_pass_dev_456 redcap \
-e "SELECT project_id, app_title FROM redcap_projects WHERE project_id = 16;"
```
---
## 📚 相关文档
| 文档名称 | 路径 | 说明 |
|---------|------|------|
| REDCap对接技术方案 | `04-开发计划/REDCap对接技术方案与实施指南.md` | Day 2技术方案 |
| MVP开发任务清单 | `04-开发计划/MVP开发任务清单.md` | 整体开发计划 |
| Postgres-Only异步任务处理指南 | `docs/02-通用能力层/Postgres-Only异步任务处理指南.md` | 队列开发规范 |
| 模块当前状态 | `00-模块当前状态与开发指南.md` | 模块整体状态 |
---
## 🚀 下一步计划
### Phase 1.5 - 质控逻辑实现
**目标**: 实现AI驱动的数据质控
**核心功能**:
1. 实现 `iit_quality_check` Worker的质控逻辑
2. 调用Dify工作流进行数据验证
3. 生成质控建议shadow state
4. 返回结果给研究者
**预估工作量**: 1-2天
---
### Phase 2 - 双向同步
**目标**: 实现AI建议回写到REDCap
**核心功能**:
1. 完善 `importRecords()` API
2. 实现shadow state审批流程
3. 经研究者确认后同步到REDCap
4. 处理冲突和版本控制
**预估工作量**: 2-3天
---
## ✅ 验收清单
- [x] RedcapAdapter API适配器完成
- [x] WebhookController Webhook接收器完成
- [x] SyncManager 轮询管理器完成
- [x] Worker注册和队列配置完成
- [x] 路由配置和Content-Type解析完成
- [x] 单元测试脚本通过test-redcap-api.ts
- [x] Webhook测试通过test-redcap-webhook.ts
- [x] 集成测试通过test-redcap-integration.ts12/12
- [x] 真实场景测试通过(新增+编辑记录)
- [x] 审计日志记录完整
- [x] 性能指标达标Webhook<10ms
- [x] 符合团队开发规范
- [x] 文档更新完成
---
## 📌 附录
### A. 环境信息
```yaml
开发环境:
- OS: Windows 11
- Node.js: v22.18.0
- PostgreSQL: 16.1 (Docker)
- REDCap: 15.8.0 (Docker)
- Backend: Fastify + Prisma
- 队列: pg-boss
Docker容器:
- redcap-apache: REDCap应用
- redcap-mysql: REDCap数据库
- ai-clinical-postgres: IIT数据库
```
### B. 关键代码文件清单
```
backend/src/modules/iit-manager/
├── adapters/
│ └── RedcapAdapter.ts (271行)
├── controllers/
│ └── WebhookController.ts (327行)
├── services/
│ └── SyncManager.ts (398行)
├── routes/
│ └── index.ts (203行)
├── index.ts (91行)
├── test-redcap-api.ts (189行)
├── test-redcap-webhook.ts (274行)
└── test-redcap-integration.ts (449行)
```
**总代码量**: ~2,200行
---
**文档维护者**: 开发团队
**最后更新**: 2026-01-02
**状态**: ✅ Day 2 开发完成