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

6.6 KiB
Raw Blame History

基础能力集成Kafka / Redis / 队列 / 事务)

总览

  • 目标: 将事件、任务、缓存、事务能力以统一规范接入 App/Core/Infrastructure 三层,替代“散落式调用”。
  • 约束: 由 Application 发起流程Core 编排业务规则且不直接依赖外设Infrastructure 提供具体实现。

1) 事务TypeORM

  • 发起层: Application用例级事务边界
  • 使用方式:
// 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 或具体 ProviderBullQueueProvider/DatabaseQueueProvider
// 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
// 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 切换 DatabaseEventBusProviderKafkaEventBusProvider
  • 规范:
    • 事件名格式: domain.aggregate.action
    • 载荷仅含必要业务字段,带上 tenantId/siteId

4) Redis缓存/限流/幂等)

  • 发起层: Application流程性控制或 Infrastructure技术性实现
  • 接入点: RedisProvidervendor/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 模块接入

  • 用例: 上传完成 → 入库附件 → 入队生成缩略图
// 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 → 发布事件 → 入队校验可用性
// 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
export const STORAGE_ADAPTER = 'STORAGE_ADAPTER';
  • 接口
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 兜底)
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 无需暴露存储端口。