Files
AIclinicalresearch/backend/src/common/README.md
HaHafeng 88cc049fb3 feat(asl): Complete Day 5 - Fulltext Screening Backend API Development
- Implement 5 core API endpoints (create task, get progress, get results, update decision, export Excel)
- Add FulltextScreeningController with Zod validation (652 lines)
- Implement ExcelExporter service with 4-sheet report generation (352 lines)
- Register routes under /api/v1/asl/fulltext-screening
- Create 31 REST Client test cases
- Add automated integration test script
- Fix PDF extraction fallback mechanism in LLM12FieldsService
- Update API design documentation to v3.0
- Update development plan to v1.2
- Create Day 5 development record
- Clean up temporary test files
2025-11-23 10:52:07 +08:00

419 lines
11 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.
# 平台基础设施Platform Infrastructure
> **版本:** V1.0
> **创建日期:** 2025-11-17
> **状态:** ✅ 实施完成
---
## 📋 概述
平台基础设施提供了一套通用的、云原生的基础能力,支持**本地开发**和**云端部署**无缝切换。
**核心设计原则适配器模式Adapter Pattern**
所有业务模块ASL、AIA、PKB等都应该使用这些平台能力而不是重复实现。
---
## 🏗️ 模块清单
| 模块 | 路径 | 状态 | 说明 |
|------|------|------|------|
| **存储服务** | `common/storage/` | ✅ 完成 | 文件上传下载(本地/OSS |
| **数据库连接池** | `config/database.ts` | ✅ 完成 | Prisma连接池配置 |
| **日志系统** | `common/logging/` | ✅ 完成 | 结构化日志JSON |
| **环境配置** | `config/env.ts` | ✅ 完成 | 统一配置管理 |
| **异步任务** | `common/jobs/` | ✅ 完成 | 长时间任务异步处理 |
| **缓存服务** | `common/cache/` | ✅ 完成 | 内存/Redis缓存 |
| **健康检查** | `common/health/` | ✅ 完成 | SAE健康检查端点 |
| **监控指标** | `common/monitoring/` | ✅ 完成 | 关键指标监控 |
---
## 📦 依赖安装
在使用之前,需要安装必需的依赖:
```bash
# 进入backend目录
cd backend
# 安装winston日志库
npm install winston
npm install -D @types/winston
```
**可选依赖(云端部署时安装):**
```bash
# 阿里云OSS当STORAGE_TYPE=oss时
npm install ali-oss
npm install -D @types/ali-oss
# Redis当CACHE_TYPE=redis时
npm install ioredis
npm install -D @types/ioredis
```
---
## 🚀 快速开始
### 1. 存储服务
```typescript
import { storage } from '@/common/storage'
// 上传文件
const buffer = await readFile('example.pdf')
const url = await storage.upload('literature/123.pdf', buffer)
// 下载文件
const data = await storage.download('literature/123.pdf')
// 删除文件
await storage.delete('literature/123.pdf')
```
**环境切换:**
```bash
# 本地开发
STORAGE_TYPE=local
# 云端部署
STORAGE_TYPE=oss
OSS_REGION=oss-cn-hangzhou
OSS_BUCKET=aiclinical-prod
OSS_ACCESS_KEY_ID=your-key-id
OSS_ACCESS_KEY_SECRET=your-key-secret
```
---
### 2. 日志系统
```typescript
import { logger } from '@/common/logging'
// 基础日志
logger.info('User logged in', { userId: 123 })
logger.error('Database error', { error: err.message })
// 带上下文的日志
const aslLogger = logger.child({ module: 'ASL', projectId: 456 })
aslLogger.info('Screening started', { count: 100 })
```
**输出格式:**
- 本地开发:彩色可读格式
- 生产环境JSON格式便于阿里云SLS解析
---
### 3. 异步任务
```typescript
import { jobQueue } from '@/common/jobs'
// 创建任务(立即返回)
const job = await jobQueue.push('asl:screening', {
projectId: 123,
literatureIds: [1, 2, 3]
})
// 返回任务ID给前端
res.send({ jobId: job.id })
// 注册处理函数
jobQueue.process('asl:screening', async (job) => {
for (const id of job.data.literatureIds) {
await processLiterature(id)
await jobQueue.updateProgress(job.id, ...)
}
return { success: true }
})
// 查询任务状态
const status = await jobQueue.getJob(job.id)
```
---
### 4. 缓存服务
```typescript
import { cache } from '@/common/cache'
// 缓存用户数据5分钟
await cache.set('user:123', userData, 60 * 5)
const user = await cache.get<User>('user:123')
// 缓存LLM响应1小时
const cacheKey = `llm:${model}:${hash(prompt)}`
const cached = await cache.get(cacheKey)
if (!cached) {
const response = await llm.chat(prompt)
await cache.set(cacheKey, response, 60 * 60)
}
```
**环境切换:**
```bash
# 本地开发
CACHE_TYPE=memory
# 云端部署
CACHE_TYPE=redis
REDIS_HOST=r-xxx.redis.aliyuncs.com
REDIS_PORT=6379
REDIS_PASSWORD=your-password
```
---
### 5. 数据库连接
```typescript
import { prisma } from '@/config/database'
// 直接使用(已配置连接池)
const users = await prisma.user.findMany()
// 获取连接数(监控用)
import { getDatabaseConnectionCount } from '@/config/database'
const count = await getDatabaseConnectionCount()
```
**云原生配置:**
```bash
DATABASE_URL=postgresql://user:pass@host:5432/db
DB_MAX_CONNECTIONS=400 # RDS最大连接数
MAX_INSTANCES=20 # SAE最大实例数
```
---
### 6. 健康检查
```typescript
import { registerHealthRoutes } from '@/common/health'
// 注册路由(在应用启动时)
await registerHealthRoutes(app)
```
**端点:**
- `GET /health/liveness` - SAE存活检查
- `GET /health/readiness` - SAE就绪检查
- `GET /health` - 详细健康检查(开发用)
---
### 7. 监控指标
```typescript
import { Metrics, requestTimingHook, responseTimingHook } from '@/common/monitoring'
// 注册中间件自动记录API响应时间
app.addHook('onRequest', requestTimingHook)
app.addHook('onResponse', responseTimingHook)
// 启动定期监控
Metrics.startPeriodicMonitoring(60000) // 每分钟
// 手动记录指标
await Metrics.recordDBConnectionCount()
Metrics.recordMemoryUsage()
// 记录LLM调用
Metrics.recordLLMCall('deepseek', 'chat', 1500, true, {
prompt: 100,
completion: 200,
total: 300
})
```
---
## 🌍 多环境支持
### 本地开发(.env.development
```bash
# 应用配置
NODE_ENV=development
PORT=3001
LOG_LEVEL=debug
# 数据库
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ai_clinical
# 存储(本地)
STORAGE_TYPE=local
LOCAL_STORAGE_DIR=uploads
# 缓存(内存)
CACHE_TYPE=memory
# 任务队列(内存)
QUEUE_TYPE=memory
```
### 云端部署(.env.production
```bash
# 应用配置
NODE_ENV=production
PORT=8080
LOG_LEVEL=info
# 数据库阿里云RDS
DATABASE_URL=postgresql://user:pass@rm-xxx.pg.rds.aliyuncs.com:5432/aiclinical
DB_MAX_CONNECTIONS=400
MAX_INSTANCES=20
# 存储阿里云OSS
STORAGE_TYPE=oss
OSS_REGION=oss-cn-hangzhou
OSS_BUCKET=aiclinical-prod
OSS_ACCESS_KEY_ID=your-key-id
OSS_ACCESS_KEY_SECRET=your-key-secret
# 缓存阿里云Redis
CACHE_TYPE=redis
REDIS_HOST=r-xxx.redis.aliyuncs.com
REDIS_PORT=6379
REDIS_PASSWORD=your-password
# 任务队列(数据库)
QUEUE_TYPE=database
```
---
## 📊 架构示意图
```
┌─────────────────────────────────────────────────────────┐
│ 业务模块层 │
│ ASL | AIA | PKB | DC | SSA | ST | UAM │
│ 只关注业务逻辑,复用平台能力 │
└─────────────────────────────────────────────────────────┘
↓ import from '@/common/'
┌─────────────────────────────────────────────────────────┐
│ 平台基础设施层Adapter Pattern
├─────────────────────────────────────────────────────────┤
│ 存储LocalAdapter ←→ OSSAdapter │
│ 缓存MemoryCacheAdapter ←→ RedisCacheAdapter │
│ 任务MemoryQueueAdapter ←→ DatabaseQueueAdapter │
│ 日志ConsoleLogger ←→ 阿里云SLS │
│ 数据库本地PostgreSQL ←→ 阿里云RDS连接池
└─────────────────────────────────────────────────────────┘
↓ 环境变量切换
┌─────────────────────────────────────────────────────────┐
│ 部署环境(零代码改动) │
│ 本地开发 | 云端SaaS | 私有化部署 | 单机版 │
└─────────────────────────────────────────────────────────┘
```
---
## ✅ 验收标准
### 功能完整性
- [x] 存储服务LocalAdapter实现完成OSSAdapter预留
- [x] 数据库:连接池配置,优雅关闭
- [x] 日志系统Winston配置JSON格式
- [x] 异步任务MemoryQueue实现完成
- [x] 缓存服务MemoryCacheAdapter实现完成RedisCacheAdapter预留
- [x] 健康检查liveness/readiness端点
- [x] 监控指标数据库连接数、内存、API响应时间
### 多环境支持
- [x] 本地开发LocalAdapter + MemoryCache + MemoryQueue
- [x] 云端部署OSSAdapter预留+ RedisCache预留+ DatabaseQueue预留
- [x] 零代码切换:通过环境变量切换
---
## 🚨 注意事项
### 1. Winston未安装
**当前状态:** 代码已完成但winston包未安装
**安装方法:**
```bash
npm install winston
npm install -D @types/winston
```
### 2. OSS/Redis待实现
**当前状态:** 接口和工厂类已完成,具体实现预留
**实施时机:** 云端部署前
**实施步骤:**
1. 安装依赖:`npm install ali-oss ioredis`
2. 取消注释:`OSSAdapter.ts``RedisCacheAdapter.ts`
3. 测试验证
### 3. Legacy模块兼容性
**策略:** Legacy模块PKB、AIA、DC保持现状新模块ASL使用平台基础设施
**迁移:** 可选按需迁移预计5小时
---
## 📚 相关文档
- [平台基础设施规划](../../../docs/09-架构实施/04-平台基础设施规划.md) - 详细设计文档
- [云原生开发规范](../../../docs/04-开发规范/08-云原生开发规范.md) - 开发规范
- [云原生部署架构指南](../../../docs/09-架构实施/03-云原生部署架构指南.md) - 部署指南
- [环境配置指南](../../../docs/07-运维文档/01-环境配置指南.md) - 环境变量配置
---
## 🎯 下一步
### 选项1安装依赖并测试推荐
```bash
cd backend
npm install winston
npm run dev
```
### 选项2开始ASL模块开发
平台基础设施已完成可以开始ASL模块开发
- 使用 `storage` 上传PDF
- 使用 `logger` 记录日志
- 使用 `jobQueue` 处理异步筛选任务
- 使用 `cache` 缓存LLM响应
---
**平台基础设施实施完成!**
**总耗时:** 约3小时Day 1: 2小时Day 2: 1小时
**代码量:** 约2000行
**模块数:** 8个核心模块
**下一步安装winston依赖开始ASL模块开发** 🚀