oh-my-muse/docs/memorys/2026-05-25-muse-cloud后端P1收口.md

253 lines
8.2 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.

# muse-cloud 后端 P1 收口留痕
## 任务背景
执行 `docs/superpowers/plans/2026-05-24-P1-muse-cloud.md` 的 P1 后端搭建任务,目标是在 `muse-cloud/` 这个 Yudao Cloud fork 基础上搭建 Muse 后端业务模块。
本次任务只负责 `muse-cloud/`,不修改 `muse-studio/``muse-admin/``docs/api-contracts/**`。P2、P3 有并行会话执行,提交时必须严格避免带入其他会话文件。
## 已完成内容
### 1. 基础环境与远端基础设施
已确认当前开发环境使用:
- Java 21
- Spring Boot 3 / Yudao Cloud fork
- PostgreSQL 连接来自 `~/.config/muse-repo/infra.env`
- Redis 连接同样来自 `~/.config/muse-repo/infra.env`
用户确认当前远端 PostgreSQL 15 可接受,不强制补 PostgreSQL 16 实例。远端 Redis 已验证 TCP 端口连通。
注意:`~/.config/muse-repo/infra.env` 内有真实凭据,不要输出密码。
### 2. DDL / Flyway SQL
已在 `muse-cloud/sql/muse/` 下形成 V1-V8
- `V1__init_content_schema.sql`
- `V2__init_account_schema.sql`
- `V3__init_meta_schema.sql`
- `V4__init_ai_schema.sql`
- `V5__init_knowledge_schema.sql`
- `V6__init_market_schema.sql`
- `V7__add_contract_operation_audit.sql`
- `V8__add_contract_workflow_and_market_interaction.sql`
关键新增:
- `muse_domain_operation_record`:统一操作审计与 `commandId` 幂等记录。
- `muse_domain_workflow_task`:承载预检、导出、重试、发布准备等异步工作流事实。
- `muse_market_favorite`:市场收藏状态。
- `muse_market_purchase`:市场购买事实。
DDL 口径:
- 使用 PostgreSQL 语法。
- 主键使用 `BIGINT GENERATED ALWAYS AS IDENTITY`
- 布尔字段使用 `BOOLEAN`
- 大文本使用 `TEXT`
- 不使用 MySQL `AUTO_INCREMENT``BIT``MEDIUMTEXT`
### 3. 合同入口持久化
新增:
- `muse-cloud/muse-framework/muse-spring-boot-starter-mybatis/src/main/java/cn/iocoder/muse/framework/mybatis/core/muse/MuseContractPersistenceService.java`
用途:
- 统一处理 Meta / Knowledge / Market / AI / Account 合同入口。
- 先执行 OpenAPI 合同路由和基础字段校验。
- 写命令先插入 `muse_domain_operation_record` 占用 `commandId`
- 再写入领域事实表或统一 workflow task。
- 最后回写操作记录的 `resource_id` 和响应快照。
- 重复 `commandId` 返回历史响应,避免重复扣费、重复发布、重复安装。
为了让 framework 包下服务能被 `muse-server` 扫描到,已在:
- `MuseMybatisAutoConfiguration`
中通过 `@Import(MuseContractPersistenceService.class)` 注册。
### 4. 模块接入
以下合同 Controller 已从纯 `MuseApiContractSupport.handle(...)` 占位响应,改为注入 `MuseContractPersistenceService`
- Meta admin
- Knowledge admin / app
- Market admin / app
- Account admin / app
- AI admin / app
并为相关模块补齐 `muse-spring-boot-starter-mybatis` 依赖。
Content 的核心作品、章节、Block 已有专用业务 Controller / Service因此没有强行纳入统一 shim。Content 扩展类 API 仍保留 catch-all 合同入口,后续应继续拆专用业务服务。
### 5. 写命令覆盖口径
通过 `MuseApiContractSupport` 中的 operation 注册表核对:
- 全部合同 operation233
- 全部写命令118
- Account 写命令9/9 已接入持久化
- AI 写命令19/19 已接入持久化
- Knowledge 写命令36/36 已接入持久化
- Market 写命令19/19 已接入持久化
- Meta 写命令8/8 已接入持久化
Content 写命令不按统一 shim 统计,因为核心 Content 已有专用实现;剩余扩展 Content API 仍需后续继续落专用 Application Service。
## 关键工程实践与避坑
### 1. 不再返回伪成功
早期 Meta / Knowledge / Market / AI / Account 合同入口主要返回占位响应,容易让前端误以为写命令已生效。
当前修正为:
- 已支持的写命令必须落业务表或 workflow task。
- 未拥有的领域写命令抛 `CONTRACT_NOT_IMPLEMENTED`
- Content 写命令由 Content 专用服务负责,不在 `MuseContractPersistenceService` 里伪造成功。
### 2. 幂等记录必须先于业务写入
并发场景下,如果先写业务表再写幂等记录,两个相同 `commandId` 请求可能同时撞业务唯一键。
当前顺序固定为:
1. 查询是否已有 `commandId` 响应。
2. 插入 `muse_domain_operation_record` 占用 `commandId`
3. 执行业务事实落库。
4. 回写操作记录响应。
### 3. 领域 owner 不能被 admin/app 入口拆散
后端按领域模块拆,不按 admin/app 拆。`admin-api``app-api` 只是入口不同,领域事实只有一个 owner。
本次实现中:
- App 写命令会对作品、知识库、文档、安装记录等做有限 owner guard。
- Meta / Market 的 `expectedVersion``expectedActiveVersion``expectedStatus` 会在后端校验。
- `commandId`、revision / expectedVersion、审计字段不只依赖前端。
### 4. 统一 workflow task 是 P1 过渡层
预检、导出、重试、发布准备等命令先统一落 `muse_domain_workflow_task`,它解决的是 P1 阶段“必须有后端事实、幂等和审计”的问题。
长期方向仍应按领域继续拆:
- Account quota request / export task
- AI evaluation run / source event retry
- Knowledge publish readiness / export / reindex
- Market bind precheck
## 验证记录
### 1. 目标测试
```bash
cd muse-cloud
JAVA_HOME=/Users/qingse/Library/Java/JavaVirtualMachines/corretto-21.0.7/Contents/Home \
PATH=/Users/qingse/Library/Java/JavaVirtualMachines/corretto-21.0.7/Contents/Home/bin:$PATH \
mvn -o test \
-pl muse-framework/muse-spring-boot-starter-mybatis,muse-server \
-am \
-Dtest=MuseContractPersistenceServiceTest,MuseApiContractSupportTest \
-Dsurefire.failIfNoSpecifiedTests=false
```
结果:
- `BUILD SUCCESS`
- `MuseContractPersistenceServiceTest` 8 个测试通过
- `MuseApiContractSupportTest` 4 个测试通过
### 2. 全量 Maven 测试
```bash
cd muse-cloud
JAVA_HOME=/Users/qingse/Library/Java/JavaVirtualMachines/corretto-21.0.7/Contents/Home \
PATH=/Users/qingse/Library/Java/JavaVirtualMachines/corretto-21.0.7/Contents/Home/bin:$PATH \
mvn test
```
最终结果:
- `BUILD SUCCESS`
- 总耗时约 `01:14 min`
### 3. PostgreSQL DDL 验收
使用远端 PG通过临时 schema 执行 `V1..V8`,最后 `ROLLBACK`
```sql
SELECT current_setting('server_version') AS pg_version,
count(*) AS muse_tables,
count(*) AS muse_triggers;
```
结果:
- PostgreSQL `15.17 (Debian 15.17-1.pgdg13+1)`
- Muse 表数量:`46`
- Muse trigger 数量:`46`
- 已回滚临时 schema不污染数据库。
### 4. Redis 连通性
```bash
nc -vz "$MUSE_REDIS_HOST" "$MUSE_REDIS_PORT"
```
结果:
- `Connection to 100.64.0.8 port 6379 succeeded`
本机缺少 `redis-cli`,因此未执行 AUTH/PING。
## 提交记录
本次 P1 相关提交:
- `6410604 feat(muse-cloud): 持久化 Muse 合同入口`
提交只包含 `muse-cloud/` 下 P1 相关文件。
提交后工作树中仍有其他会话文件,不属于 P1
- `.DS_Store`
- `muse-admin/**`
- `docs/memorys/2026-05-25-muse-admin管理端搭建.md`
- `docs/superpowers/plans/P1-execution-prompt.md`
- `docs/superpowers/plans/P3-execution-prompt.md`
- `precommit-scan-oh-my-muse-20260524.md`
后续提交时需要继续避开这些文件,除非对应 owner 明确要求。
## 未完成与后续建议
### 1. DTO 仍需继续精细化
当前读接口很多仍返回通用 JSON 行、操作记录或 workflow task不等于完全符合 OpenAPI DTO 的最终形态。
后续应按领域补齐 Application Query Service 和 response assembler。
### 2. Content 扩展 API 仍需专用实现
Content 核心作品、章节、Block 已有业务实现但规划、导入、解析、导出、MetaProjection、SuggestionMerge 等扩展 API 仍应继续拆专用服务。
### 3. Workflow task 需要异步执行器
`muse_domain_workflow_task` 当前只保证命令事实、幂等和审计。后续需要补:
- 任务调度
- 状态流转
- 失败重试
- 结果 payload
- 领域事件或 outbox
### 4. PG16 最终环境仍未实际验收
用户已确认可使用 PG15 推进。若后续要严格对齐计划中的 PostgreSQL 16需要重新在 PG16 实例上跑一次 `V1..V8` 和应用启动验收。