Files
wwjcloud-nest-v1/admin/docs/src/wwjcloud/ai/integration.md
万物街 1cd5d3bdef feat: 完成 NestJS 后端核心底座开发 (M1-M6) 和 Ant Design Vue 前端迁移
主要更新:
1. 后端核心底座完成 (M1-M6):
   - 健康检查、指标监控、分布式锁
   - 事件总线、队列系统、事务管理
   - 安全守卫、多租户隔离、存储适配器
   - 审计日志、配置管理、多语言支持

2. 前端迁移到 Ant Design Vue:
   - 从 Element Plus 迁移到 Ant Design Vue
   - 完善 system 模块 (role/menu/dept)
   - 修复依赖和配置问题

3. 文档完善:
   - AI 开发工作流文档
   - 架构约束和开发规范
   - 项目进度跟踪

4. 其他改进:
   - 修复编译错误和类型问题
   - 完善测试用例
   - 优化项目结构
2025-08-27 11:24:22 +08:00

154 lines
6.6 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.
## 基础能力集成Kafka / Redis / 队列 / 事务)
### 总览
- 目标: 将事件、任务、缓存、事务能力以统一规范接入 App/Core/Infrastructure 三层,替代“散落式调用”。
- 约束: 由 Application 发起流程Core 编排业务规则且不直接依赖外设Infrastructure 提供具体实现。
### 1) 事务TypeORM
- 发起层: Application用例级事务边界
- 使用方式:
```ts
// application/xxx.app.service.ts
constructor(private readonly dataSource: DataSource, private readonly core: XxxCoreService) {}
async runUseCase(dto: Dto) {
return await this.dataSource.transaction(async (manager) => {
// 将 manager 注入到仓储实现(通过请求域注入或方法透传)
await this.core.handle(dto); // Core 内仅调用仓储接口
});
}
```
- 规范:
- 事务只在 Application 层开启Core 不直接操作事务对象
- 多仓储参与时基于同一 `EntityManager`
### 2) 队列Bull/BullMQ 或 DB 队列)
- 发起层: Application用例结束后入队
- 接入点: `UnifiedQueueService` 或具体 Provider`BullQueueProvider`/`DatabaseQueueProvider`
```ts
// application/xxx.app.service.ts
constructor(private readonly queue: UnifiedQueueService) {}
await this.queue.addJob('media', 'generateThumbnail', { attId }, { attempts: 3, delay: 0 });
```
- 处理器建议放置:
- `infrastructure/queues/xxx.processor.ts` 或独立消费模块
- 规范:
- 入队数据为最小必要字段ID/键大对象存储DB再查
### 3) 事件Kafka / DB Outbox
- 发起层: Application领域事件在用例完成后发布
- 接入点: `DomainEventService`(绑定 `IEventBus`,默认 DB Outbox可切 Kafka
```ts
// application/xxx.app.service.ts
constructor(private readonly events: DomainEventService) {}
await this.events.publishEvent(
'system.settings.storage.updated',
String(siteId),
String(siteId),
{ storageType },
);
```
- 配置切换:
- 通过 `EventBusModule` 的 provider 切换 `DatabaseEventBusProvider``KafkaEventBusProvider`
- 规范:
- 事件名格式: `domain.aggregate.action`
- 载荷仅含必要业务字段,带上 `tenantId/siteId`
### 4) Redis缓存/限流/幂等)
- 发起层: Application流程性控制或 Infrastructure技术性实现
- 接入点: `RedisProvider``vendor/redis`
- 常见场景:
- 读多写少配置缓存:`sys_config` 读取后短缓存
- 上传限流/防刷:基于 IP/UID 的计数器
- 幂等:`SETNX` + 过期控制
### 5) 存储(本地/云)
- 发起层: Application 调用 Core 规则后,委托 Infrastructure Provider 落地
- 接入点: `infrastructure/providers/*``vendor/storage/*`(如 `LocalStorageAdapter`
- 规范:
- Provider 通过接口注入,便于切换 OSS/COS/Qiniu
### 6) 在三层中的放置原则
- Application: 事务、入队、发事件、协调多 Core 服务
- Core: 纯业务规则/策略与仓储接口;不直接依赖 Kafka/Redis/队列
- Infrastructure: 队列消费者、存储/HTTP/Redis 具体实现、TypeORM 仓储实现
### 7) 示例Upload 模块接入
- 用例: 上传完成 → 入库附件 → 入队生成缩略图
```ts
// application/upload.app.service.ts
await this.dataSource.transaction(async (manager) => {
const att = await this.core.validateAndPlan(fileMeta);
await this.attachmentRepo.withManager(manager).save(att);
});
await this.queue.addJob('media', 'generateThumbnail', { attId: att.id });
```
### 8) 示例Settings.Storage 接入
- 用例: 切换默认存储 → 写 `sys_config` → 发布事件 → 入队校验可用性
```ts
// application/storage-settings.app.service.ts
await this.dataSource.transaction(async (manager) => {
await this.core.ensureExclusiveDefault(type);
await this.sysConfigRepo.withManager(manager).setValue(key, value);
});
await this.events.publishEvent('system.settings.storage.updated', String(siteId), String(siteId), { type });
await this.queue.addJob('ops', 'validateStorage', { type, siteId });
```
### 9) 配置与健康
- 配置在 `VendorModule`/`EventBusModule` 注入;通过 `ConfigService` 读取连接信息
- 健康检查:将 Redis/队列/事件写入健康聚合输出
### 10) 方案Bvendor/storage 标准结构(平台外设)
```
vendor/storage/
├── index.ts # 统一导出(接口、Token、模块、适配器)
├── storage.module.ts # 可配置模块(选择具体实现)
├── tokens.ts # 注入Token常量(如 STORAGE_ADAPTER)
├── interfaces/
│ ├── storage-adapter.ts # 适配器接口(平台标准)
│ └── types.ts # 通用类型(上传结果、签名参数等)
├── adapters/
│ ├── local.adapter.ts # 本地实现
│ ├── aliyun-oss.adapter.ts # 阿里云实现
│ ├── qcloud-cos.adapter.ts # 腾讯云实现
│ └── qiniu.adapter.ts # 七牛云实现
├── providers/
│ ├── storage.provider.ts # 工厂: 按配置/站点解析适配器
│ └── registry.ts # 多实例注册表 Map<siteId, adapter> + TTL
├── health/storage.health.ts # 健康检查(各实现可选实现)
├── config/schema.ts # 配置Schema(必需项校验)
└── __tests__/
├── storage.contract.spec.ts # 契约测试(接口一致性)
└── adapters/*.spec.ts # 各实现最小测试
```
- Token
```ts
export const STORAGE_ADAPTER = 'STORAGE_ADAPTER';
```
- 接口
```ts
export interface StorageAdapter {
upload(params: { key: string; content: Buffer | NodeJS.ReadableStream; mime?: string }): Promise<{ url: string; key: string }>;
delete(key: string): Promise<void>;
signUpload?(params: { key: string; expiresSec?: number; mime?: string }): Promise<{ url: string; headers?: Record<string,string>; fields?: Record<string,string> }>;
healthCheck?(): Promise<boolean>;
}
```
- 按 site_id 解析(站点启用 > 跟随系统 > local 兜底)
```ts
function resolveAdapter(siteId: number): StorageAdapter {
const enabled = readSiteEnabled(siteId); // storage_xxx with is_use
const type = enabled?.type ?? readPlatformDefault();
const options = enabled?.options ?? readPlatformOptions(type) ?? {};
return registry.getOrCreate(siteId, type, options);
}
```
- 本地隔离路径:`upload/site_{siteId}/...`
- 健康检查:对活跃站点适配器定期 `healthCheck()` 并聚合到 Health
> 说明方案B 将“三方存储”视为外设,接口与实现均在 vendor业务通过 Token 注入与按站点解析工厂使用core 无需暴露存储端口。