fix:删除无用文件
This commit is contained in:
@@ -1,48 +0,0 @@
|
|||||||
# JDK17 + Mockito + CI Stability Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Stabilize local/CI test execution by fixing Mockito agent startup behavior and pinning CI to JDK 17.
|
|
||||||
|
|
||||||
**Architecture:** Configure Maven Surefire to preload Mockito as a javaagent and set required JVM flags to avoid runtime self-attach failures. Add a CI workflow that always uses JDK 17 and runs compile/test checks. Update README for explicit developer/CI runtime expectations.
|
|
||||||
|
|
||||||
**Tech Stack:** Maven Surefire, Mockito, GitHub Actions, JDK 17, Spring Boot 3.5
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Build/Test runtime hardening
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `pom.xml`
|
|
||||||
|
|
||||||
1. Add explicit `mockito.version` property.
|
|
||||||
2. Add `maven-surefire-plugin` with `argLine` including:
|
|
||||||
- `-Djdk.attach.allowAttachSelf=true`
|
|
||||||
- `-XX:+EnableDynamicAgentLoading`
|
|
||||||
- `-javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar`
|
|
||||||
|
|
||||||
### Task 2: CI JDK pinning
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `.github/workflows/ci.yml`
|
|
||||||
|
|
||||||
1. Add workflow on `push` + `pull_request`.
|
|
||||||
2. Use `actions/setup-java` with Temurin `17`.
|
|
||||||
3. Run `mvn -q -DskipTests compile` then `mvn -q test`.
|
|
||||||
|
|
||||||
### Task 3: Documentation sync
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `README.md`
|
|
||||||
|
|
||||||
1. Add explicit local recommended JDK 17 note.
|
|
||||||
2. Add CI note: workflow runs JDK 17 and compile+test.
|
|
||||||
3. Add troubleshooting note for Mockito agent behavior on newer JDKs.
|
|
||||||
|
|
||||||
### Task 4: Verification
|
|
||||||
|
|
||||||
**Commands:**
|
|
||||||
1. `mvn -q -DskipTests compile`
|
|
||||||
2. `mvn -q test` (sandbox)
|
|
||||||
3. `mvn -q test` (escalated fallback if sandbox attach restrictions block)
|
|
||||||
4. Key checks with `rg` for workflow and surefire config.
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
# PCIe密码卡强类型封装设计(第一期)
|
|
||||||
|
|
||||||
- 日期:2026-02-28
|
|
||||||
- 范围:基于 `0018接口.pdf`(国密标准SDF)与 `PCIE密码卡应用接口说明书.docx`(SDFE扩展)
|
|
||||||
- 目标:为上层提供强类型业务方法,屏蔽底层JNA细节
|
|
||||||
|
|
||||||
## 1. 设计目标与约束
|
|
||||||
|
|
||||||
### 1.1 目标
|
|
||||||
|
|
||||||
1. 提供强类型业务方法,不要求上层使用 `execute(command, params)`。
|
|
||||||
2. 采用短连接会话模型:每个业务方法内部完成 `openDevice/openSession/call/closeSession/closeDevice`。
|
|
||||||
3. 第一期开通核心子集接口,覆盖设备管理、会话、HMAC、LMK与常用密钥管理。
|
|
||||||
4. 统一错误模型与错误码映射,便于上层处理与运维排障。
|
|
||||||
|
|
||||||
### 1.2 非目标
|
|
||||||
|
|
||||||
1. 不在第一期覆盖文档所有SDF/SDFE接口。
|
|
||||||
2. 不在第一期做多设备负载均衡与高并发优化。
|
|
||||||
3. 不在第一期实现JNI桥代码生成。
|
|
||||||
|
|
||||||
## 2. 方案选型
|
|
||||||
|
|
||||||
### 2.1 备选方案
|
|
||||||
|
|
||||||
1. 动态命令入口(`execute(command, params)`)+ 强类型外观。
|
|
||||||
2. 纯强类型服务(推荐)。
|
|
||||||
3. 从头文件自动生成绑定与服务代码。
|
|
||||||
|
|
||||||
### 2.2 选型结论
|
|
||||||
|
|
||||||
采用方案2:新增 `PcieCryptoService` 及其 `JnaPcieCryptoService` 实现,
|
|
||||||
强类型方法直接调用JNA映射,统一通过短连接模板管理句柄生命周期。
|
|
||||||
|
|
||||||
## 3. 总体架构
|
|
||||||
|
|
||||||
### 3.1 分层
|
|
||||||
|
|
||||||
1. `PcieCryptoService`:面向上层的强类型业务接口。
|
|
||||||
2. `JnaPcieCryptoService`:服务实现,调用 `PcieNativeLibrary`。
|
|
||||||
3. `PcieSessionTemplate`:统一短连接模板。
|
|
||||||
4. `PcieNativeLibrary`:JNA native函数映射。
|
|
||||||
5. `PcieErrorMapper`:错误码映射(`retCode -> 业务可读信息`)。
|
|
||||||
|
|
||||||
### 3.2 调用路径
|
|
||||||
|
|
||||||
上层业务 -> `PcieCryptoService` 强类型方法 -> `PcieSessionTemplate` -> `PcieNativeLibrary` -> 厂商 `.so`
|
|
||||||
|
|
||||||
## 4. 第一期开通接口(核心子集)
|
|
||||||
|
|
||||||
### 4.1 设备与会话
|
|
||||||
|
|
||||||
1. `getDeviceNumber()` -> `SDFE_GetDeviceNumber`
|
|
||||||
2. `getNormalDeviceNumber()` -> `SDFE_GetNormalDeviceNumber`
|
|
||||||
3. `deviceSelfTest()` -> `SDFE_DeviceSelfTest`
|
|
||||||
4. `deviceConfGet()` -> `SDFE_DeviceConfGet`
|
|
||||||
5. `initIdentify(oldPin, newPin)` -> `SDFE_InitIdentify`
|
|
||||||
|
|
||||||
> 注:`open/close` 作为模板内部行为,不暴露给上层业务接口。
|
|
||||||
|
|
||||||
### 4.2 常用密钥管理(用户确认的8组)
|
|
||||||
|
|
||||||
1. `generateKeyPairEcc` / `generateKeyPairRsa`
|
|
||||||
2. `generateKek`
|
|
||||||
3. `backupUserKey` / `recoverUserKey`
|
|
||||||
4. `backupKek` / `recoverKek`
|
|
||||||
5. `deleteUserKey` / `deleteKek`
|
|
||||||
6. `statusUserKeyEcc` / `statusUserKeyRsa`
|
|
||||||
7. `statusKek`
|
|
||||||
8. `changePrivateKeyAccessPassword`
|
|
||||||
|
|
||||||
### 4.3 HMAC
|
|
||||||
|
|
||||||
1. `hmac(algId, key, data)`
|
|
||||||
2. 内部流程:`SDFE_HmacInit` -> `SDFE_HmacUpdate` -> `SDFE_HmacFinal`
|
|
||||||
|
|
||||||
### 4.4 LMK(核心)
|
|
||||||
|
|
||||||
1. `generateLmk` / `loadLmk` / `backupLmk` / `recoverLmk` / `destroyLmk`
|
|
||||||
2. `checkLmk` / `exportLmkSeedMac`
|
|
||||||
|
|
||||||
## 5. 强类型模型
|
|
||||||
|
|
||||||
### 5.1 请求对象
|
|
||||||
|
|
||||||
1. `GenerateKeyRequest`:`keyIndex`, `keyBits`, `keyType`
|
|
||||||
2. `RecoverUserKeyRequest`:`keyIndex`, `keyType`, `cipherKeyData`, `storeFlag`
|
|
||||||
3. `RecoverKekRequest`:`keyIndex`, `cipherKeyData`
|
|
||||||
4. `ChangePrivateKeyPasswordRequest`:`keyIndex`, `oldPassword`, `newPassword`
|
|
||||||
5. `HmacRequest`:`algId`, `key`, `data`
|
|
||||||
|
|
||||||
### 5.2 响应对象
|
|
||||||
|
|
||||||
1. `OperationResult`:`success`, `retCode`, `message`
|
|
||||||
2. `DeviceCountResult`:`deviceNumber`, `normalDeviceNumber`
|
|
||||||
3. `DeviceConfResult`:映射 `SDFE_DeviceConf`
|
|
||||||
4. `BackupUserKeyResult` / `BackupKekResult`:`data`, `length`
|
|
||||||
5. `KeyStatusResult`:`keyState`
|
|
||||||
6. `HmacResult`:`hmac`, `hmacLength`
|
|
||||||
|
|
||||||
## 6. 会话模板(短连接)
|
|
||||||
|
|
||||||
定义统一模板方法:
|
|
||||||
|
|
||||||
```text
|
|
||||||
executeWithSession(apiName, callback):
|
|
||||||
SDF_OpenDevice
|
|
||||||
SDF_OpenSession
|
|
||||||
callback(session)
|
|
||||||
SDF_CloseSession
|
|
||||||
SDF_CloseDevice
|
|
||||||
```
|
|
||||||
|
|
||||||
约束:
|
|
||||||
|
|
||||||
1. 所有强类型方法必须通过模板执行。
|
|
||||||
2. 关闭失败仅记录日志,不覆盖主调用错误。
|
|
||||||
3. 模板保证异常场景也能回收句柄。
|
|
||||||
|
|
||||||
## 7. 错误处理
|
|
||||||
|
|
||||||
1. `retCode == 0`:成功。
|
|
||||||
2. `retCode != 0`:抛 `PcieCryptoException(apiName, retCode, mappedMessage)`。
|
|
||||||
3. 映射文档补充错误码:
|
|
||||||
- `SDR_UKEYERR`
|
|
||||||
- `SDR_GENKEYERR`
|
|
||||||
- `SDR_STATEERR`
|
|
||||||
- `SDR_RETRYERR`
|
|
||||||
- `SDR_DEVICE_BUSY`
|
|
||||||
- `SDR_RET_ERR_STATUS`
|
|
||||||
- `SDR_RET_INIT_STATUS`
|
|
||||||
- `SDR_RET_LOGINED`
|
|
||||||
- `SDR_RET_GD32_TIMEOUT`
|
|
||||||
4. 参数校验失败在服务层抛 `IllegalArgumentException`,不下发至设备。
|
|
||||||
|
|
||||||
## 8. 并发与安全
|
|
||||||
|
|
||||||
1. 第一期开启串行访问(单设备锁)避免状态错乱。
|
|
||||||
2. PIN/口令参数不打印明文日志。
|
|
||||||
3. 密钥备份字节在服务层保持二进制,不做文本日志输出。
|
|
||||||
|
|
||||||
## 9. 对上层的使用方式
|
|
||||||
|
|
||||||
示例:
|
|
||||||
|
|
||||||
1. `pcieCryptoService.generateLmk()`
|
|
||||||
2. `pcieCryptoService.backupKek(keyIndex, outBufferSize)`
|
|
||||||
3. `pcieCryptoService.hmac(request)`
|
|
||||||
|
|
||||||
上层仅依赖强类型接口与DTO,不直接依赖JNA类型和指针。
|
|
||||||
|
|
||||||
## 10. 验收标准
|
|
||||||
|
|
||||||
1. 强类型接口可完成第一期核心子集调用。
|
|
||||||
2. 每个方法均使用短连接模板。
|
|
||||||
3. 统一异常中包含 `apiName + retCode + mappedMessage`。
|
|
||||||
4. `mvn -DskipTests compile` 通过。
|
|
||||||
5. 关键路径联调用例可跑通:
|
|
||||||
- `getDeviceNumber`
|
|
||||||
- `deviceConfGet`
|
|
||||||
- `hmac`
|
|
||||||
- `generateKek + statusKek`
|
|
||||||
|
|
||||||
## 11. 后续扩展
|
|
||||||
|
|
||||||
1. 第二期覆盖U盾与内部密钥管理。
|
|
||||||
2. 第三期覆盖全量SDF/SDFE并补充结构体严格对齐校验。
|
|
||||||
3. 加入真实设备集成测试与回放测试。
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# PCIe 真卡联调与冒烟检查清单
|
|
||||||
|
|
||||||
## 1. 前置条件
|
|
||||||
|
|
||||||
- 部署环境为目标架构(与生产一致的 CPU/OS/libc)。
|
|
||||||
- 已安装厂商 `.so`,并可被进程访问。
|
|
||||||
- 服务配置为 JNA 真卡模式:
|
|
||||||
- `tms.crypto-card.enabled=true`
|
|
||||||
- `tms.crypto-card.mode=JNA`
|
|
||||||
- `tms.crypto-card.vendor-lib-path` 或 `tms.crypto-card.vendor-lib-name` 正确
|
|
||||||
- `tms.crypto-card.strict-alg-id-validation=true`(若厂商扩展算法可临时关闭)
|
|
||||||
- 已知内部接口鉴权令牌 `X-Internal-Token`。
|
|
||||||
|
|
||||||
## 2. 核心检查项(必须通过)
|
|
||||||
|
|
||||||
1. 设备与会话
|
|
||||||
- `GET /api/v1/device/crypto/device-count`
|
|
||||||
- `GET /api/v1/device/crypto/device-info`
|
|
||||||
- `POST /api/v1/device/crypto/self-test`
|
|
||||||
2. 基础密码能力
|
|
||||||
- 随机数:`GET /api/v1/device/crypto/random?length=16`
|
|
||||||
- 摘要:`POST /api/v1/device/crypto/digest`
|
|
||||||
- HMAC:`POST /api/v1/device/crypto/hmac`
|
|
||||||
3. 对称能力
|
|
||||||
- 明文密钥加解密:`/encrypt/plain` + `/decrypt/plain`
|
|
||||||
- KEK 生成与状态:`/kek/generate` + `/kek/status`
|
|
||||||
4. 主密钥状态
|
|
||||||
- `GET /api/v1/device/crypto/lmk/seed-mac`
|
|
||||||
|
|
||||||
验收标准:
|
|
||||||
|
|
||||||
- `ApiResponse.success == true`
|
|
||||||
- `ApiResponse.code == 200`
|
|
||||||
- 返回长度字段与 Base64 解码长度一致
|
|
||||||
- 错误日志中无 native 崩溃/段错误
|
|
||||||
|
|
||||||
## 3. 高风险专项
|
|
||||||
|
|
||||||
### 3.1 `SDFE_ImportEncKeyPair_ECC`(结构体直传)
|
|
||||||
|
|
||||||
- 用最小可用样本执行导入流程。
|
|
||||||
- 成功后立即查询相关密钥状态接口验证导入结果。
|
|
||||||
- 若出现参数错误,优先检查结构体字段对齐与 `unsigned long` 位宽。
|
|
||||||
|
|
||||||
### 3.2 `ECCCipher` 变长字段边界
|
|
||||||
|
|
||||||
- 对不同明文长度执行 ECC 加密路径。
|
|
||||||
- 记录返回 `ECCCipher.l` 的最大值。
|
|
||||||
- 若接近当前上限(`C_MAX_LEN`),必须提升上限并复测。
|
|
||||||
|
|
||||||
### 3.3 算法标识白名单
|
|
||||||
|
|
||||||
- 对业务实际用到的所有 `algId` 跑一遍。
|
|
||||||
- 若被严格校验拦截,补充到 `Gm0018AlgorithmIds` 后再回归。
|
|
||||||
|
|
||||||
## 4. 失败排查顺序
|
|
||||||
|
|
||||||
1. 配置错误:库路径、库名、鉴权 token。
|
|
||||||
2. 运行时依赖:`ldd`/动态库缺失。
|
|
||||||
3. 参数编码:Base64 入参、长度字段、结构体大小。
|
|
||||||
4. 算法标识:`algId` 是否在白名单。
|
|
||||||
5. 厂商错误码:结合 `PcieErrorMapper` 与厂商文档定位。
|
|
||||||
|
|
||||||
## 5. 回归策略
|
|
||||||
|
|
||||||
- 每次升级以下任一项,都执行本清单:
|
|
||||||
- JDK 版本
|
|
||||||
- 厂商 `.so` 版本
|
|
||||||
- JNA 结构体定义
|
|
||||||
- `JnaPcieCryptoService` 参数转换逻辑
|
|
||||||
|
|
||||||
## 6. 自动化模板
|
|
||||||
|
|
||||||
- 使用脚本:`scripts/pcie_realcard_smoke.sh`
|
|
||||||
- 建议在联调机和预生产各执行一次,并保留日志归档。
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
# CISD 初始化 API Curl 样例集
|
|
||||||
|
|
||||||
- 日期:2026-03-02
|
|
||||||
- 适用接口前缀:`/api/v1/device`、`/api/v1/init`
|
|
||||||
- 说明:以下样例用于联调,不包含生产鉴权与审计策略
|
|
||||||
|
|
||||||
## 1. 公共变量
|
|
||||||
|
|
||||||
```bash
|
|
||||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
|
||||||
INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 查询设备预置版本信息
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -sS \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/device/status" | jq
|
|
||||||
```
|
|
||||||
|
|
||||||
预期关键字段:
|
|
||||||
|
|
||||||
1. `data.presetProductType`:`ENTERPRISE|INDIRECT|DIRECT`
|
|
||||||
2. `data.presetVersion`
|
|
||||||
|
|
||||||
## 3. 企业/间参请求体(RabbitMQ)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > /tmp/cisd-init-standard-rabbit.json <<'JSON'
|
|
||||||
{
|
|
||||||
"orgCodeType": "BIC",
|
|
||||||
"orgCode": "AAAABBBBXXX",
|
|
||||||
"orgNameCn": "测试机构",
|
|
||||||
"orgNameEn": "TEST BANK",
|
|
||||||
"deployMode": "SINGLE",
|
|
||||||
"nodes": {
|
|
||||||
"node01Ip": "10.0.0.11"
|
|
||||||
},
|
|
||||||
"mq": {
|
|
||||||
"mqType": "RABBITMQ",
|
|
||||||
"channelUsername": "cisd_channel_user",
|
|
||||||
"channelPassword": "cisd_channel_pass"
|
|
||||||
},
|
|
||||||
"licenses": {
|
|
||||||
"receiverLicenseFileId": "file-receiver-001"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 企业/间参请求体(TLQ)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > /tmp/cisd-init-standard-tlq.json <<'JSON'
|
|
||||||
{
|
|
||||||
"orgCodeType": "BIC",
|
|
||||||
"orgCode": "AAAABBBBXXX",
|
|
||||||
"orgNameCn": "测试机构",
|
|
||||||
"orgNameEn": "TEST BANK",
|
|
||||||
"deployMode": "DUAL",
|
|
||||||
"nodes": {
|
|
||||||
"node01Ip": "10.0.0.11",
|
|
||||||
"node02Ip": "10.0.0.12"
|
|
||||||
},
|
|
||||||
"mq": {
|
|
||||||
"mqType": "TLQ",
|
|
||||||
"channelUsername": "cisd_channel_user",
|
|
||||||
"channelPassword": "cisd_channel_pass",
|
|
||||||
"tlqLicenseFileId": "file-tlq-license-001"
|
|
||||||
},
|
|
||||||
"licenses": {
|
|
||||||
"receiverLicenseFileId": "file-receiver-001"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. 轻量化直参请求体(RABBITMQ_TLQ)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > /tmp/cisd-init-direct-tlq.json <<'JSON'
|
|
||||||
{
|
|
||||||
"orgCodeType": "BIC",
|
|
||||||
"orgCode": "AAAABBBBXXX",
|
|
||||||
"orgNameCn": "测试机构",
|
|
||||||
"orgNameEn": "TEST BANK",
|
|
||||||
"deployMode": "DUAL",
|
|
||||||
"nodes": {
|
|
||||||
"node01Ip": "10.0.1.11",
|
|
||||||
"node02Ip": "10.0.1.12"
|
|
||||||
},
|
|
||||||
"mq": {
|
|
||||||
"mqType": "RABBITMQ_TLQ",
|
|
||||||
"channelUsername": "cisd_channel_user",
|
|
||||||
"channelPassword": "cisd_channel_pass",
|
|
||||||
"tlqLicenseFileId": "file-tlq-license-001"
|
|
||||||
},
|
|
||||||
"licenses": {
|
|
||||||
"receiverLicenseFileId": "file-receiver-001",
|
|
||||||
"cfgZipFileId": "/opt/cpconfig.cfg"
|
|
||||||
},
|
|
||||||
"signServer": {
|
|
||||||
"signHost": "172.30.1.101",
|
|
||||||
"signPort": 50006,
|
|
||||||
"signType": "Infosec",
|
|
||||||
"signCertDn": "CN=051@AAAABBBBXXX@7321@1,OU=Org,OU=CIPS,O=CFCA OCA1,C=CN",
|
|
||||||
"signCertSn": "1154809590",
|
|
||||||
"signPassword": "secret"
|
|
||||||
},
|
|
||||||
"directTlq": {
|
|
||||||
"localNodeSeq": "A",
|
|
||||||
"upstreamInstitutions": "CIPSCNSHXXX;CIPSCNWXXXX",
|
|
||||||
"upstreamCocCount": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. 轻量化直参请求体(RABBITMQ_CFMQ)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > /tmp/cisd-init-direct-cfmq.json <<'JSON'
|
|
||||||
{
|
|
||||||
"orgCodeType": "BIC",
|
|
||||||
"orgCode": "AAAABBBBXXX",
|
|
||||||
"orgNameCn": "测试机构",
|
|
||||||
"orgNameEn": "TEST BANK",
|
|
||||||
"deployMode": "SINGLE",
|
|
||||||
"nodes": {
|
|
||||||
"node01Ip": "10.0.1.11"
|
|
||||||
},
|
|
||||||
"mq": {
|
|
||||||
"mqType": "RABBITMQ_CFMQ",
|
|
||||||
"channelUsername": "cisd_channel_user",
|
|
||||||
"channelPassword": "cisd_channel_pass",
|
|
||||||
"cfmqConfigFileId": "/pmts/cfg/cfmqapi_trans.properties"
|
|
||||||
},
|
|
||||||
"licenses": {
|
|
||||||
"receiverLicenseFileId": "file-receiver-001",
|
|
||||||
"cfgZipFileId": "/opt/cpconfig.cfg"
|
|
||||||
},
|
|
||||||
"signServer": {
|
|
||||||
"signHost": "172.30.1.101",
|
|
||||||
"signPort": 50006,
|
|
||||||
"signType": "Infosec",
|
|
||||||
"signCertDn": "CN=051@AAAABBBBXXX@7321@1,OU=Org,OU=CIPS,O=CFCA OCA1,C=CN",
|
|
||||||
"signCertSn": "1154809590",
|
|
||||||
"signPassword": "secret"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7. 初始化任务执行链路(通用)
|
|
||||||
|
|
||||||
将 `<REQUEST_JSON>` 替换为上面任一 json 文件路径。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
REQUEST_JSON="/tmp/cisd-init-standard-rabbit.json"
|
|
||||||
|
|
||||||
# 1) preview
|
|
||||||
curl -sS -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/init/preview" \
|
|
||||||
-d @"${REQUEST_JSON}" | jq
|
|
||||||
|
|
||||||
# 2) create task
|
|
||||||
TASK_ID="$(curl -sS -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/init/tasks" \
|
|
||||||
-d @"${REQUEST_JSON}" | jq -r '.data.taskId')"
|
|
||||||
|
|
||||||
echo "TASK_ID=${TASK_ID}"
|
|
||||||
|
|
||||||
# 3) execute task
|
|
||||||
curl -sS -X POST \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/init/tasks/${TASK_ID}/execute" | jq
|
|
||||||
|
|
||||||
# 4) query steps
|
|
||||||
curl -sS \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/init/tasks/${TASK_ID}/steps" | jq
|
|
||||||
```
|
|
||||||
|
|
||||||
## 8. 单步日志查询(失败定位)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
STEP_NO=3
|
|
||||||
curl -sS \
|
|
||||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
|
||||||
"${BASE_URL}/api/v1/init/tasks/${TASK_ID}/steps/${STEP_NO}/log" | jq -r '.data.content'
|
|
||||||
```
|
|
||||||
|
|
||||||
## 9. 常见问题
|
|
||||||
|
|
||||||
1. 直参 TLQ 报 `directTlq is required`:请求体缺 `directTlq` 三字段。
|
|
||||||
2. `APP_MQ_CREDENTIALS_APPLY` 失败:应用配置匹配路径无文件或无写权限。
|
|
||||||
3. MQ 连接失败:确认 `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY` 与收发器解密密钥一致。
|
|
||||||
|
|
||||||
## 10. 一键执行脚本(推荐)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x scripts/cisd_init_flow.sh
|
|
||||||
REQUEST_JSON=/tmp/cisd-init-standard-rabbit.json \
|
|
||||||
BASE_URL=http://127.0.0.1:8080 \
|
|
||||||
INTERNAL_TOKEN=change-me-internal-token \
|
|
||||||
./scripts/cisd_init_flow.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
输出目录默认:`/tmp/cisd-init-run/run-<timestamp>`,包含每一步请求响应与失败日志抓取结果。
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
# CISD 初始化真机联调与回滚手册
|
|
||||||
|
|
||||||
- 日期:2026-03-02
|
|
||||||
- 适用版本:`ENTERPRISE` / `INDIRECT` / `DIRECT`
|
|
||||||
- 适用代码基线:已包含 `APP_MQ_CREDENTIALS_APPLY`、`direct_db_init`、`tlq_init_cfg`
|
|
||||||
|
|
||||||
## 1. 目的
|
|
||||||
|
|
||||||
1. 在目标设备上完成初始化关键路径联调。
|
|
||||||
2. 验证三类版本在“预部署完成后,仅做客户化初始化”的边界下可稳定运行。
|
|
||||||
3. 提供失败后的快速回滚与重试指引。
|
|
||||||
|
|
||||||
## 2. 关键实现映射(联调前必须确认)
|
|
||||||
|
|
||||||
1. 企业/间参步骤链:
|
|
||||||
`RENDER_CONFIG -> SET_(RABBITMQ|TLQ) -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY`
|
|
||||||
2. 轻量化直参(TLQ)步骤链:
|
|
||||||
`RENDER_CONFIG -> MQ_USER_APPLY -> DB_INIT(direct_db_init) -> TLQ_INIT_CFG(tlq_init_cfg) -> VERIFY`
|
|
||||||
3. 轻量化直参(CFMQ)步骤链:
|
|
||||||
`RENDER_CONFIG -> MQ_USER_APPLY -> DB_INIT(direct_db_init) -> CFMQ_APPLY -> VERIFY`
|
|
||||||
4. 通道账号密码写回应用配置时默认加密:
|
|
||||||
`DESede(3DES) + secretKey=ABCDEFGHIJKLMN1234567890 + HEX(upper)`。
|
|
||||||
|
|
||||||
## 3. 联调前置检查
|
|
||||||
|
|
||||||
## 3.1 环境变量基线
|
|
||||||
|
|
||||||
在 TMS 进程环境确认以下参数:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "$TMS_CISD_PRESET_PRODUCT_TYPE"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_MODE"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_STANDARD_CPCONFIG_PATH"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_DIRECT_DB_SCRIPT_DIR"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_DIRECT_TLQ_INIT_CFG_DIR"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_1"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_2"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_ENCRYPT_ENABLED"
|
|
||||||
echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY"
|
|
||||||
```
|
|
||||||
|
|
||||||
建议值:
|
|
||||||
|
|
||||||
1. `TMS_INIT_EXECUTOR_MODE=LOCAL`
|
|
||||||
2. `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_ENCRYPT_ENABLED=true`
|
|
||||||
3. `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY` 与现场收发器解密密钥一致。
|
|
||||||
|
|
||||||
## 3.2 目录与脚本存在性
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -l /home/cmep4i/cpconfig.cfg
|
|
||||||
ls -l /home/cmep4i/cpackage/toolsh/{setfraq.sh,setftq.sh,setsql.sh,setsptp.sh}
|
|
||||||
ls -l /opt/CAE_Install_Base_Resource/DB/setsql.sh
|
|
||||||
ls -l /opt/CAE_Install_App_Resource/CAE/init_cfg.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3.3 MQ 与配置文件可写性
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -l /home/cmep4i/cmsp/application-prd*.properties
|
|
||||||
ls -l /home/cmep4i/cmtp/application-prd*.properties
|
|
||||||
which rabbitmqctl
|
|
||||||
which rabbitmqadmin
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 联调执行清单(统一流程)
|
|
||||||
|
|
||||||
## 4.1 接口执行顺序
|
|
||||||
|
|
||||||
1. `GET /api/v1/device/status`
|
|
||||||
2. `POST /api/v1/init/preview`
|
|
||||||
3. `POST /api/v1/init/task`
|
|
||||||
4. `POST /api/v1/init/task/{taskId}/execute`
|
|
||||||
5. `GET /api/v1/init/task/{taskId}/steps`
|
|
||||||
6. 失败时逐步查看日志:`GET /api/v1/init/task/{taskId}/steps/{stepNo}/log`
|
|
||||||
|
|
||||||
## 4.2 用例矩阵(最小集合)
|
|
||||||
|
|
||||||
1. 企业版 + RabbitMQ
|
|
||||||
2. 企业版 + TLQ
|
|
||||||
3. 间参版 + RabbitMQ
|
|
||||||
4. 轻量化直参 + RABBITMQ_TLQ(必须带 `directTlq` 三字段)
|
|
||||||
5. 轻量化直参 + RABBITMQ_CFMQ
|
|
||||||
|
|
||||||
## 4.3 直参 TLQ 请求体附加字段
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"directTlq": {
|
|
||||||
"localNodeSeq": "A",
|
|
||||||
"upstreamInstitutions": "CIPSCNSHXXX;CIPSCNWXXXX",
|
|
||||||
"upstreamCocCount": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. 关键验收点
|
|
||||||
|
|
||||||
1. `RENDER_CONFIG` 后,`cpconfig.cfg` 中机构号、节点、签名参数、`MQ_TYPE` 已替换。
|
|
||||||
2. `MQ_USER_APPLY` 后,RabbitMQ 中存在通道用户,且具备目标 vhost 权限。
|
|
||||||
3. `MQ_QUEUE_APPLY` 后,业务队列创建成功(企业/间参)。
|
|
||||||
4. `APP_MQ_CREDENTIALS_APPLY` 后,`spring.rabbitmq.username/password` 已更新且为密文(非明文)。
|
|
||||||
5. `DB_INIT` 生成或替换的 SQL 文件可执行,无路径/权限错误。
|
|
||||||
6. `VERIFY` 成功,任务最终状态 `SUCCESS`。
|
|
||||||
|
|
||||||
## 6. 失败定位顺序
|
|
||||||
|
|
||||||
1. 配置错误:版本预置、环境变量、路径。
|
|
||||||
2. 权限错误:TMS 进程用户对脚本和配置文件不可写。
|
|
||||||
3. 脚本依赖缺失:`rabbitmqctl/rabbitmqadmin`、Java、数据库客户端。
|
|
||||||
4. 参数不完整:直参 TLQ 缺 `directTlq` 字段。
|
|
||||||
5. 密钥不一致:写回密文与收发器解密密钥不匹配导致 MQ 连接失败。
|
|
||||||
|
|
||||||
## 7. 回滚策略(按层次)
|
|
||||||
|
|
||||||
## 7.1 执行前备份(强制)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
TS=$(date +%Y%m%d%H%M%S)
|
|
||||||
mkdir -p /tmp/cisd-init-backup-$TS
|
|
||||||
cp -a /home/cmep4i/cpconfig.cfg /tmp/cisd-init-backup-$TS/
|
|
||||||
cp -a /home/cmep4i/cmsp/application-prd*.properties /tmp/cisd-init-backup-$TS/ 2>/dev/null || true
|
|
||||||
cp -a /home/cmep4i/cmtp/application-prd*.properties /tmp/cisd-init-backup-$TS/ 2>/dev/null || true
|
|
||||||
echo "/tmp/cisd-init-backup-$TS"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7.2 配置回滚
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp -a /tmp/cisd-init-backup-<TS>/cpconfig.cfg /home/cmep4i/cpconfig.cfg
|
|
||||||
cp -a /tmp/cisd-init-backup-<TS>/application-prd*.properties /home/cmep4i/cmsp/ 2>/dev/null || true
|
|
||||||
cp -a /tmp/cisd-init-backup-<TS>/application-prd*.properties /home/cmep4i/cmtp/ 2>/dev/null || true
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7.3 MQ 回滚(按需)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 删除通道用户(示例)
|
|
||||||
rabbitmqctl delete_user <channelUsername>
|
|
||||||
|
|
||||||
# 删除业务队列(示例,按实际创建队列名执行)
|
|
||||||
rabbitmqadmin --username=admin --password=admin --vhost=/ delete queue name=<queueName>
|
|
||||||
rabbitmqadmin --username=admin --password=admin --vhost=/RQ delete queue name=<queueName>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7.4 数据库回滚(按实际 SQL 执行情况)
|
|
||||||
|
|
||||||
1. 若仅生成 SQL 未执行:删除临时生成物即可。
|
|
||||||
2. 若已执行入库:使用预先准备的回滚 SQL 或从数据库备份恢复。
|
|
||||||
3. 严禁在无备份情况下直接清库重建。
|
|
||||||
|
|
||||||
## 8. 重试策略
|
|
||||||
|
|
||||||
1. 先回滚配置和 MQ 变更,再重建任务重试,不复用失败任务。
|
|
||||||
2. 每次仅变更一个变量(如路径、密钥、账号),避免多变量同时变化。
|
|
||||||
3. 连续两次同一步失败,先停止重试,导出该步骤日志并人工排查根因。
|
|
||||||
|
|
||||||
## 9. 交付物归档
|
|
||||||
|
|
||||||
每次联调需归档:
|
|
||||||
|
|
||||||
1. `taskId`、版本类型、请求参数(脱敏后)。
|
|
||||||
2. 步骤执行日志目录:`/tmp/tms-init-logs/<taskId>/`。
|
|
||||||
3. 回滚操作记录(是否执行、执行人、时间)。
|
|
||||||
4. 最终结论:通过/失败及根因。
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
# CISD Init Request Schema Spec (Preset-Version Driven)
|
|
||||||
|
|
||||||
## 1. Scope
|
|
||||||
This document defines the frontend request schema for CISD initialization in TMS when product version is preset by device metadata.
|
|
||||||
|
|
||||||
- Frontend must call `GET /api/v1/device/status` first.
|
|
||||||
- If `presetProductType` is empty or invalid, initialization is forbidden.
|
|
||||||
- Frontend must render version-specific form fields automatically; user does not manually choose version.
|
|
||||||
|
|
||||||
## 2. Device status fields used by frontend
|
|
||||||
`/api/v1/device/status` response includes:
|
|
||||||
|
|
||||||
- `presetProductType`: `ENTERPRISE | INDIRECT | DIRECT`
|
|
||||||
- `presetVersion`: preset package version
|
|
||||||
- `presetSource`: where preset was loaded from (e.g., `CONFIG`, future `DB`)
|
|
||||||
|
|
||||||
## 3. Init preview request payload
|
|
||||||
Endpoint: `POST /api/v1/init/preview`
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"orgCodeType": "BIC",
|
|
||||||
"orgCode": "AAAABBBBXXX",
|
|
||||||
"orgNameCn": "示例机构",
|
|
||||||
"orgNameEn": "Example Bank",
|
|
||||||
"deployMode": "DUAL",
|
|
||||||
"nodes": {
|
|
||||||
"node01Ip": "10.0.0.1",
|
|
||||||
"node02Ip": "10.0.0.2",
|
|
||||||
"node03Ip": "127.0.0.1",
|
|
||||||
"node04Ip": "127.0.0.1"
|
|
||||||
},
|
|
||||||
"mq": {
|
|
||||||
"mqType": "RABBITMQ",
|
|
||||||
"channelUsername": "channel_user",
|
|
||||||
"channelPassword": "channel_password",
|
|
||||||
"tlqLicenseFileId": "file-tlq-license",
|
|
||||||
"cfmqConfigFileId": "file-cfmq-config"
|
|
||||||
},
|
|
||||||
"licenses": {
|
|
||||||
"receiverLicenseFileId": "file-receiver-license",
|
|
||||||
"cfgZipFileId": "file-cfg-zip"
|
|
||||||
},
|
|
||||||
"signServer": {
|
|
||||||
"signHost": "172.30.1.101",
|
|
||||||
"signPort": 50006,
|
|
||||||
"signType": "Infosec",
|
|
||||||
"signCertDn": "CN=...",
|
|
||||||
"signCertSn": "1154809590",
|
|
||||||
"signPassword": "***"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. Mandatory fields by product type
|
|
||||||
|
|
||||||
### 4.1 Common mandatory fields (all versions)
|
|
||||||
- `orgCodeType`, `orgCode`, `orgNameCn`
|
|
||||||
- `deployMode`
|
|
||||||
- `nodes.node01Ip`
|
|
||||||
- `mq.mqType`, `mq.channelUsername`, `mq.channelPassword`
|
|
||||||
- `licenses.receiverLicenseFileId`
|
|
||||||
|
|
||||||
### 4.2 ENTERPRISE / INDIRECT
|
|
||||||
Allowed values:
|
|
||||||
- `deployMode`: `SINGLE | DUAL`
|
|
||||||
- `mq.mqType`: `RABBITMQ | TLQ`
|
|
||||||
|
|
||||||
Conditional required fields:
|
|
||||||
- `deployMode=DUAL` -> `nodes.node02Ip`
|
|
||||||
- `mqType=TLQ` -> `mq.tlqLicenseFileId`
|
|
||||||
|
|
||||||
### 4.3 DIRECT
|
|
||||||
Allowed values:
|
|
||||||
- `deployMode`: `SINGLE | DUAL | QUAD`
|
|
||||||
- `mq.mqType`: `RABBITMQ_TLQ | RABBITMQ_CFMQ`
|
|
||||||
|
|
||||||
Always required:
|
|
||||||
- `licenses.cfgZipFileId`
|
|
||||||
- `signServer.signHost`
|
|
||||||
- `signServer.signPort`
|
|
||||||
- `signServer.signType`
|
|
||||||
- `signServer.signCertDn`
|
|
||||||
- `signServer.signCertSn`
|
|
||||||
- `signServer.signPassword`
|
|
||||||
|
|
||||||
Conditional required fields:
|
|
||||||
- `deployMode=DUAL|QUAD` -> `nodes.node02Ip`
|
|
||||||
- `deployMode=QUAD` -> `nodes.node03Ip`, `nodes.node04Ip`
|
|
||||||
- `mqType=RABBITMQ_TLQ` -> `mq.tlqLicenseFileId`
|
|
||||||
- `mqType=RABBITMQ_CFMQ` -> `mq.cfmqConfigFileId`
|
|
||||||
|
|
||||||
## 5. Prefilled vs user-input fields
|
|
||||||
|
|
||||||
### 5.1 Prefilled and hidden from frontend
|
|
||||||
- Product preset metadata: version type and package version
|
|
||||||
- Database deployment credentials and root/app user passwords
|
|
||||||
- RabbitMQ admin username/password
|
|
||||||
|
|
||||||
### 5.2 User input fields
|
|
||||||
- Institution identity and node addresses
|
|
||||||
- MQ channel username/password
|
|
||||||
- Version-conditional file uploads (receiver license, TLQ license, CFMQ config, direct CFG zip)
|
|
||||||
- Direct sign server information
|
|
||||||
|
|
||||||
## 6. Validation behavior
|
|
||||||
- Validation errors return code `4001` with field message.
|
|
||||||
- Missing/invalid preset product type returns business error and initialization is blocked.
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
# CISD Init Request Schema DTO Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Replace placeholder init preview request with a production-ready CISD initialization request DTO and server-side rule validation based on preset product type.
|
|
||||||
|
|
||||||
**Architecture:** Keep the current single-module Spring Boot structure. Introduce strong-typed nested DTOs for init request payload, centralize preset version/product-type sourcing in configuration properties (as current phase baseline), and enforce cross-field conditional rules in `InitService` before preview generation. Surface preset product type in `/api/v1/device/info` for frontend auto-rendering.
|
|
||||||
|
|
||||||
**Tech Stack:** JDK 17, Spring Boot 3.5, Jakarta Bean Validation, JUnit 5.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Add failing tests for init request rule validation
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write failing tests**
|
|
||||||
- Add tests for:
|
|
||||||
- missing preset product type should reject init preview.
|
|
||||||
- enterprise + TLQ should require `tlqLicenseFileId`.
|
|
||||||
- direct + `RABBITMQ_CFMQ` should require `cfmqConfigFileId`, `cfgZipFileId`, and sign server fields.
|
|
||||||
- valid enterprise request should pass and generate summary.
|
|
||||||
|
|
||||||
**Step 2: Run targeted tests to verify red**
|
|
||||||
- Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
- Expected: FAIL because `InitService` still uses old DTO and has no rule engine.
|
|
||||||
|
|
||||||
### Task 2: Implement strong-typed init request DTO model
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java`
|
|
||||||
|
|
||||||
**Step 1: Replace old placeholder fields**
|
|
||||||
- Remove `version/nodeCount`.
|
|
||||||
- Add nested models for:
|
|
||||||
- basic institution fields
|
|
||||||
- deploy mode + nodes
|
|
||||||
- mq settings
|
|
||||||
- licenses
|
|
||||||
- sign server
|
|
||||||
|
|
||||||
**Step 2: Add validation annotations**
|
|
||||||
- Add required constraints for common fields (`orgCodeType`, `orgCode`, `orgNameCn`, `deployMode`, `node01Ip`, `mqType`, `channelUsername`, `channelPassword`, `receiverLicenseFileId`).
|
|
||||||
|
|
||||||
**Step 3: Keep model minimal and serializable**
|
|
||||||
- Use static inner classes with getters/setters only.
|
|
||||||
|
|
||||||
### Task 3: Add preset product type source and expose in device info
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `src/main/java/com/cisd/tms/common/config/properties/CisdPresetProperties.java`
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/device/dto/DeviceInfoResponse.java`
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/device/service/DeviceService.java`
|
|
||||||
- Modify: `src/main/resources/application.yml`
|
|
||||||
|
|
||||||
**Step 1: Add configuration properties bean**
|
|
||||||
- Prefix: `tms.cisd.preset`
|
|
||||||
- Fields: `productType`, `version`, `source`.
|
|
||||||
|
|
||||||
**Step 2: Extend device status response**
|
|
||||||
- Add `presetProductType`, `presetVersion`, `presetSource`.
|
|
||||||
|
|
||||||
**Step 3: Populate response from preset config**
|
|
||||||
- Inject `CisdPresetProperties` into `DeviceService` and map values.
|
|
||||||
|
|
||||||
### Task 4: Implement rule validation in InitService
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPreviewResponse.java`
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPlanTemplateResponse.java`
|
|
||||||
|
|
||||||
**Step 1: Add preset guard**
|
|
||||||
- If preset product type missing/invalid, throw `BizException` and block preview/template.
|
|
||||||
|
|
||||||
**Step 2: Add product-type conditional validation**
|
|
||||||
- Enterprise/Indirect:
|
|
||||||
- deploy mode only `SINGLE/DUAL`
|
|
||||||
- mq type only `RABBITMQ/TLQ`
|
|
||||||
- TLQ requires `tlqLicenseFileId`
|
|
||||||
- DUAL requires `node02Ip`
|
|
||||||
- Direct:
|
|
||||||
- deploy mode `SINGLE/DUAL/QUAD`
|
|
||||||
- mq type `RABBITMQ_TLQ/RABBITMQ_CFMQ`
|
|
||||||
- `cfgZipFileId` required
|
|
||||||
- sign server fields required
|
|
||||||
- TLQ requires `tlqLicenseFileId`
|
|
||||||
- CFMQ requires `cfmqConfigFileId`
|
|
||||||
- DUAL/QUAD require `node02Ip`; QUAD require `node03Ip/node04Ip`
|
|
||||||
|
|
||||||
**Step 3: Produce meaningful preview summary**
|
|
||||||
- Set response fields: resolved product type, step count estimate, and concise summary.
|
|
||||||
|
|
||||||
### Task 5: Add developer-facing validation spec doc
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `docs/plans/2026-03-02-cisd-init-request-schema-spec.md`
|
|
||||||
|
|
||||||
**Step 1: Document payload JSON schema shape**
|
|
||||||
- Include common object structure and conditional fields by product type.
|
|
||||||
|
|
||||||
**Step 2: Document prefilled vs user-input fields**
|
|
||||||
- Explicitly list DB creds and RabbitMQ admin creds as prefilled-only.
|
|
||||||
|
|
||||||
### Task 6: Verify and stabilize
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- N/A
|
|
||||||
|
|
||||||
**Step 1: Run targeted tests**
|
|
||||||
- `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
|
|
||||||
**Step 2: Run compile check**
|
|
||||||
- `mvn -q -DskipTests compile`
|
|
||||||
|
|
||||||
**Step 3: Run full test suite if stable**
|
|
||||||
- `mvn -q test`
|
|
||||||
|
|
||||||
**Step 4: Record results in response**
|
|
||||||
- Include changed files, command outputs summary, remaining risks.
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# CISD 标准版初始化支持方式设计
|
|
||||||
|
|
||||||
## 背景
|
|
||||||
当前 TMS 将标准版初始化统一抽象为 `mqType=RABBITMQ|TLQ`。这与实际部署介质不完全一致:
|
|
||||||
- `ENTERPRISE` 支持 `RABBITMQ` 和 `TLQ` 两种互斥模式。
|
|
||||||
- `INDIRECT` 支持 `仅 RabbitMQ` 和 `RabbitMQ + TLQ` 两种模式。
|
|
||||||
- `INDIRECT` 的 `RabbitMQ + TLQ` 并不是纯 `TLQ`,仍需执行 RabbitMQ 用户、队列和应用配置。
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
在不破坏现有接口字段名的前提下,修正标准版初始化参数校验、步骤编排和执行条件,使其与部署介质和脚本行为一致。
|
|
||||||
|
|
||||||
## 约束
|
|
||||||
- 保留前端请求字段 `mq.mqType`,避免接口字段名变更带来的联调成本。
|
|
||||||
- 仅修改 `modules/init` 范围内代码和 `docs/openapi/cisd-init` 文档。
|
|
||||||
- 不调整出厂前预装边界;本次仍只覆盖初始化阶段。
|
|
||||||
|
|
||||||
## 方案选择
|
|
||||||
### 方案 A:重命名字段为 `supportMode`
|
|
||||||
优点:语义最准确。
|
|
||||||
缺点:破坏现有接口,前后端和历史任务数据都要联动修改。
|
|
||||||
|
|
||||||
### 方案 B:保留 `mqType` 字段名,按产品解释枚举值
|
|
||||||
优点:改动最小,能直接修正行为。
|
|
||||||
缺点:字段名与实际语义存在轻微偏差,需要通过文档解释。
|
|
||||||
|
|
||||||
### 方案 C:继续保留当前模型,仅靠执行器特殊判断
|
|
||||||
优点:表面改动更少。
|
|
||||||
缺点:校验、预检、步骤预览、OpenAPI 全部失真,后续维护成本更高。
|
|
||||||
|
|
||||||
## 采用方案
|
|
||||||
采用方案 B。
|
|
||||||
|
|
||||||
## 调整后的 `mqType` 语义
|
|
||||||
- `ENTERPRISE`: `RABBITMQ` | `TLQ`
|
|
||||||
- `INDIRECT`: `RABBITMQ` | `RABBITMQ_TLQ`
|
|
||||||
- `DIRECT`: `RABBITMQ_TLQ` | `RABBITMQ_CFMQ`
|
|
||||||
|
|
||||||
## 标准版步骤编排
|
|
||||||
### ENTERPRISE + RABBITMQ
|
|
||||||
`RENDER_CONFIG -> FILE_PREPARE -> SET_RABBITMQ -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY`
|
|
||||||
|
|
||||||
### ENTERPRISE + TLQ
|
|
||||||
`RENDER_CONFIG -> FILE_PREPARE -> SET_TLQ -> TLQ_CONF_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> VERIFY`
|
|
||||||
|
|
||||||
### INDIRECT + RABBITMQ
|
|
||||||
`RENDER_CONFIG -> FILE_PREPARE -> SET_RABBITMQ -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY`
|
|
||||||
|
|
||||||
### INDIRECT + RABBITMQ_TLQ
|
|
||||||
`RENDER_CONFIG -> FILE_PREPARE -> SET_TLQ -> TLQ_CONF_APPLY -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY`
|
|
||||||
|
|
||||||
## 脚本映射
|
|
||||||
- `SET_RABBITMQ` -> `cpackage/toolsh/setfraq.sh`
|
|
||||||
- `SET_TLQ` -> `cpackage/toolsh/setftq.sh`
|
|
||||||
- `TLQ_CONF_APPLY` -> `cpackage/toolsh/settlq.sh`
|
|
||||||
- `DB_INIT` -> `cpackage/toolsh/setsql.sh`
|
|
||||||
- `DEPLOY_RECEIVER` -> `cpackage/toolsh/setsptp.sh`
|
|
||||||
- `MQ_USER_APPLY` -> 标准版 `setuprabq.sh` staging 执行
|
|
||||||
- `MQ_QUEUE_APPLY` -> 标准版 `addrabq_R_01.sh` / `addrabq_R_02.sh` staging 执行
|
|
||||||
|
|
||||||
## 执行条件
|
|
||||||
- `ENTERPRISE + TLQ` 跳过 RabbitMQ 用户、队列和应用账号写回。
|
|
||||||
- `INDIRECT + RABBITMQ_TLQ` 保留 RabbitMQ 用户、队列和应用账号写回。
|
|
||||||
- `FILE_PREPARE` 在 `TLQ` 或 `RABBITMQ_TLQ` 模式下均需准备 TLQ license。
|
|
||||||
|
|
||||||
## 测试重点
|
|
||||||
- `ENTERPRISE + TLQ` 预检通过且步骤中包含 `TLQ_CONF_APPLY`,不包含 RabbitMQ 相关步骤。
|
|
||||||
- `INDIRECT + RABBITMQ_TLQ` 预检通过且步骤中同时包含 `TLQ_CONF_APPLY` 与 RabbitMQ 相关步骤。
|
|
||||||
- `INDIRECT + TLQ` 作为非法值被拒绝。
|
|
||||||
- `ENTERPRISE + RABBITMQ_TLQ` 作为非法值被拒绝。
|
|
||||||
- `APP_MQ_CREDENTIALS_APPLY` 在 `ENTERPRISE + TLQ` 下跳过,在 `INDIRECT + RABBITMQ_TLQ` 下执行。
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
# CISD Standard Init Support Mode Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** 修正标准版 CISD 初始化中 `ENTERPRISE` 和 `INDIRECT` 的支持方式建模、步骤编排和执行条件。
|
|
||||||
|
|
||||||
**Architecture:** 保留 `mqType` 字段名,但将其解释为按产品区分的支持方式枚举;服务层负责校验和步骤编排,执行器负责按产品与模式判定脚本是否实际执行或跳过。
|
|
||||||
|
|
||||||
**Tech Stack:** Java 17, Spring Boot 3, JUnit 5, OpenAPI YAML/JSON
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: 固化设计与枚举语义
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `docs/plans/2026-03-06-cisd-standard-init-support-mode-design.md`
|
|
||||||
- Create: `docs/plans/2026-03-06-cisd-standard-init-support-mode-plan.md`
|
|
||||||
|
|
||||||
**Step 1: 保存设计文档**
|
|
||||||
保存版本差异、步骤编排和脚本映射。
|
|
||||||
|
|
||||||
**Step 2: 保存实施计划**
|
|
||||||
记录测试先行的修改顺序。
|
|
||||||
|
|
||||||
### Task 2: 先补服务层失败测试
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: 写 ENTERPRISE TLQ 的预检和步骤测试**
|
|
||||||
断言 `TLQ_CONF_APPLY` 存在,`MQ_USER_APPLY/MQ_QUEUE_APPLY/APP_MQ_CREDENTIALS_APPLY` 不存在。
|
|
||||||
|
|
||||||
**Step 2: 写 INDIRECT RABBITMQ_TLQ 的预检和步骤测试**
|
|
||||||
断言 `TLQ_CONF_APPLY`、`MQ_USER_APPLY`、`MQ_QUEUE_APPLY`、`APP_MQ_CREDENTIALS_APPLY` 同时存在。
|
|
||||||
|
|
||||||
**Step 3: 写非法组合测试**
|
|
||||||
覆盖 `INDIRECT + TLQ`、`ENTERPRISE + RABBITMQ_TLQ` 被拒绝。
|
|
||||||
|
|
||||||
**Step 4: 运行定向测试,确认红灯**
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: 至少新增用例失败。
|
|
||||||
|
|
||||||
### Task 3: 实现服务层校验和编排
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
|
|
||||||
**Step 1: 调整标准版允许枚举**
|
|
||||||
按 `productType` 区分 `ENTERPRISE` 与 `INDIRECT`。
|
|
||||||
|
|
||||||
**Step 2: 调整标准版 license 校验**
|
|
||||||
`ENTERPRISE + TLQ` 与 `INDIRECT + RABBITMQ_TLQ` 都要求 `tlqLicenseFileId`。
|
|
||||||
|
|
||||||
**Step 3: 新增 `TLQ_CONF_APPLY` 编排**
|
|
||||||
更新 `defaultSteps` 和命令模板。
|
|
||||||
|
|
||||||
**Step 4: 运行服务层测试,确认绿灯**
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 4: 先补执行器失败测试
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: 写 ENTERPRISE TLQ 下 RabbitMQ 应用配置应跳过的测试**
|
|
||||||
|
|
||||||
**Step 2: 写 INDIRECT RABBITMQ_TLQ 下 RabbitMQ 用户步骤应执行的测试**
|
|
||||||
|
|
||||||
**Step 3: 写 `TLQ_CONF_APPLY` 命令解析或任务步骤断言测试**
|
|
||||||
|
|
||||||
**Step 4: 运行定向测试,确认红灯**
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: 至少新增用例失败。
|
|
||||||
|
|
||||||
### Task 5: 实现执行器条件修正
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Modify: `src/main/java/com/cisd/tms/modules/init/config/InitCommandProfileService.java`(如需补充注释/兼容逻辑)
|
|
||||||
|
|
||||||
**Step 1: 抽取标准版 RabbitMQ 是否启用的判断**
|
|
||||||
- `ENTERPRISE`: 仅 `RABBITMQ`
|
|
||||||
- `INDIRECT`: `RABBITMQ` 和 `RABBITMQ_TLQ`
|
|
||||||
|
|
||||||
**Step 2: 修正 `MQ_USER_APPLY` / `MQ_QUEUE_APPLY` 条件**
|
|
||||||
|
|
||||||
**Step 3: 修正 `APP_MQ_CREDENTIALS_APPLY` 条件**
|
|
||||||
|
|
||||||
**Step 4: 运行执行器测试,确认绿灯**
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 6: 同步 OpenAPI 文档
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `docs/openapi/cisd-init.openapi.yaml`
|
|
||||||
- Modify: `docs/openapi/cisd-init.openapi.json`
|
|
||||||
|
|
||||||
**Step 1: 更新 `mqType` 描述**
|
|
||||||
明确不同产品的合法取值。
|
|
||||||
|
|
||||||
**Step 2: 更新请求示例和步骤含义说明**
|
|
||||||
体现 `TLQ_CONF_APPLY` 与 `INDIRECT` 的双通道模式。
|
|
||||||
|
|
||||||
### Task 7: 完整验证
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: 运行模块定向测试**
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 2: 运行编译验证**
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: 人工检查关键路径**
|
|
||||||
检查 `ENTERPRISE + TLQ`、`INDIRECT + RABBITMQ_TLQ` 的任务步骤和命令模板。
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
# CIPS Auto Deployment Refactor Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** 在保留“基础环境预置”的前提下,将 CISD/CIPS 初始化从“cpconfig.cfg 驱动 vendor shell”逐步升级为“TMS 后端接管客户化渲染、输出物管理和执行编排”的自动化部署流程。
|
|
||||||
|
|
||||||
**Architecture:** 运维继续负责操作系统、目录、基础软件、介质上传解压、数据库和中间件平台级账号密码等与客户无关的预置动作;TMS 负责根据前端参数生成部署上下文,输出渲染后的配置和 SQL,按版本/支持方式编排客户化初始化步骤,并产出可审计的日志、配置快照和结果摘要。vendor 原始脚本默认只读,优先采用 staging 临时渲染执行,而不是直接改写介质本体。
|
|
||||||
|
|
||||||
**Tech Stack:** Spring Boot 3, Shell staging execution, 模板渲染, TiDB SQL 初始化, RabbitMQ/TLQ, CMSP/CMTP, Nginx/Web 发布
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: 固化“预置层 / 初始化层”边界
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
|
|
||||||
**Step 1: 明确定义预置层**
|
|
||||||
预置层仅包含与客户参数无关的动作:
|
|
||||||
- OS 用户、用户组、目录、权限创建
|
|
||||||
- JDK、RabbitMQ/TLQ/TiDB/Nginx 安装
|
|
||||||
- 防火墙和服务注册
|
|
||||||
- 安装介质上传、解压、静态资源预放置
|
|
||||||
- 数据库账号密码、中间件管理员账号密码等平台级凭据预置
|
|
||||||
- 许可证预置(如果出厂前已拿到)
|
|
||||||
|
|
||||||
**Step 2: 明确定义初始化层**
|
|
||||||
初始化层仅包含客户化动作:
|
|
||||||
- 机构号 / BIC / CIPS ID / LEI
|
|
||||||
- 节点 IP / 数据库地址
|
|
||||||
- RabbitMQ 通道账号密码
|
|
||||||
- RabbitMQ 用户 / 队列 / VHost 初始化
|
|
||||||
- TLQ 配置替换
|
|
||||||
- SQL 渲染与导库编排
|
|
||||||
- CMSP / CMTP / filetrans 配置渲染
|
|
||||||
- Nginx upstream / organization.json / Web 发布
|
|
||||||
- 服务启动与验收
|
|
||||||
|
|
||||||
**Step 3: 删除“初始化阶段执行预置脚本”的需求**
|
|
||||||
以下脚本只保留为预置脚本,不纳入 TMS 初始化主流程:
|
|
||||||
- `setpd.sh`
|
|
||||||
- `opencport.sh`
|
|
||||||
- `install_newpackage.sh`
|
|
||||||
- `setrabqstart.sh`
|
|
||||||
- `setxsd.sh`
|
|
||||||
- `setngservice.sh`
|
|
||||||
- `pongx.sh`
|
|
||||||
|
|
||||||
### Task 2: 固化部署上下文模型
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
|
|
||||||
**Step 1: 区分“前端输入参数”和“后端部署上下文”**
|
|
||||||
前端输入参数只承载业务输入;后端部署上下文承载可直接渲染文件和执行脚本的派生值。
|
|
||||||
|
|
||||||
**Step 2: 部署上下文仅保留初始化阶段所需客户化字段**
|
|
||||||
部署上下文至少应包含:
|
|
||||||
- `productType`
|
|
||||||
- `supportMode`
|
|
||||||
- `myCipsIdOrBic`
|
|
||||||
- `mq01Ip`
|
|
||||||
- `mq02Ip`
|
|
||||||
- `app01Ip`
|
|
||||||
- `app02Ip`
|
|
||||||
- `dbIp`
|
|
||||||
- `bicCode`
|
|
||||||
- `cipsId`
|
|
||||||
- `leiCode`
|
|
||||||
- `organizationNameCn`
|
|
||||||
- `organizationNameEn`
|
|
||||||
- `signVendor`
|
|
||||||
- `signIp`
|
|
||||||
- `signPort`
|
|
||||||
- `signDn`
|
|
||||||
- `signPasswordEnc`
|
|
||||||
|
|
||||||
**Step 3: 平台级凭据不进入初始化上下文**
|
|
||||||
以下内容由预置层提供,不作为初始化接口输入:
|
|
||||||
- 数据库用户名 / 密码
|
|
||||||
- RabbitMQ 管理员账号 / 密码
|
|
||||||
- TiDB 管理员账号 / 密码
|
|
||||||
|
|
||||||
**Step 4: supportMode 显式按产品定义**
|
|
||||||
- `ENTERPRISE`: `RABBITMQ` / `TLQ`
|
|
||||||
- `INDIRECT`: `RABBITMQ` / `RABBITMQ_TLQ`
|
|
||||||
- `DIRECT`: `RABBITMQ_TLQ` / `RABBITMQ_CFMQ`
|
|
||||||
|
|
||||||
### Task 3: 优先接管数据库初始化
|
|
||||||
|
|
||||||
**Status (2026-03-09):** 标准版已完成第一阶段落地,初始化编排已拆为 `DB_RENDER -> DB_APPLY`,并在 task staging 目录生成渲染后 SQL 包;后续仍需补强真实导库命令与结果校验。
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setsql.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/CMEP-DML.sql`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/sql_script_tmp/CMTP-01-raq.sql`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/sql_script_tmp/CMTP-01-tlq.sql`
|
|
||||||
|
|
||||||
**Step 1: 让后端输出渲染后的 SQL 包**
|
|
||||||
输出至少包含:
|
|
||||||
- `CMTP-01.sql`
|
|
||||||
- `CMEP-DML.sql`
|
|
||||||
- 其他导库所需脚本快照
|
|
||||||
|
|
||||||
**Step 2: 数据库导入凭据继续由预置层提供**
|
|
||||||
初始化阶段不再输入和修改数据库账号密码;TMS 只负责:
|
|
||||||
- 渲染 SQL
|
|
||||||
- 组织导入顺序
|
|
||||||
- 记录执行结果
|
|
||||||
|
|
||||||
**Step 3: DB_INIT 从“纯脚本黑盒”升级为“渲染 + 执行”双阶段**
|
|
||||||
拆成:
|
|
||||||
- `DB_RENDER`
|
|
||||||
- `DB_APPLY`
|
|
||||||
|
|
||||||
**Step 4: 保留 vendor 导库脚本作为执行器,而不是模板引擎**
|
|
||||||
如果短期不能完全替代 `setsql.sh`,则至少做到:
|
|
||||||
- 模板由后端渲染
|
|
||||||
- vendor 脚本只负责导入,不再负责替换占位符
|
|
||||||
|
|
||||||
### Task 4: 接管应用配置输出物
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setsptp.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/application-prd-ci01.properties`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmtp/01/application-prd-ci01.properties`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/filetrans.properties`
|
|
||||||
|
|
||||||
**Step 1: 后端直接输出以下配置快照**
|
|
||||||
- `application-prd*.properties`
|
|
||||||
- `filetrans.properties`
|
|
||||||
- 标准版 RabbitMQ 通道账号密码回写结果
|
|
||||||
|
|
||||||
**Step 2: 数据库连接凭据保持预置,不由初始化阶段改写**
|
|
||||||
应用配置接管范围仅覆盖客户化字段,不覆盖预置层数据库连接凭据。
|
|
||||||
|
|
||||||
**Step 3: 将 setsptp.sh 从“渲染 + 拷贝”降级为“拷贝器”**
|
|
||||||
短期目标:
|
|
||||||
- 配置替换由后端完成
|
|
||||||
- `setsptp.sh` 仅做 JAR / 目录拷贝
|
|
||||||
|
|
||||||
**Step 4: 禁止敏感信息输出到步骤日志**
|
|
||||||
渲染日志中不得出现密码明文或密文。
|
|
||||||
|
|
||||||
### Task 5: 接管 Nginx / Web 客户化
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/setngx.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setweb.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/nginx.conf`
|
|
||||||
|
|
||||||
**Step 1: 新增 Nginx/Web 相关步骤**
|
|
||||||
至少新增:
|
|
||||||
- `NGINX_CONFIG_APPLY`
|
|
||||||
- `WEB_CONFIG_APPLY`
|
|
||||||
|
|
||||||
**Step 2: 后端渲染输出物**
|
|
||||||
- `nginx.conf`
|
|
||||||
- `organization.json`
|
|
||||||
- Web 发布目录快照或发布日志
|
|
||||||
|
|
||||||
**Step 3: 不再把 setweb.sh 作为首批高收益改造对象本体**
|
|
||||||
优先由后端接管组织名称和 nginx upstream 渲染,再决定是否保留 `setweb.sh` 作为拷贝器。
|
|
||||||
|
|
||||||
### Task 6: 建立显式启动顺序
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sh/sh/stcmep_cent.sh`
|
|
||||||
|
|
||||||
**Step 1: 将“部署”和“启动”拆开**
|
|
||||||
当前 `DEPLOY_RECEIVER` 不能同时承载“拷贝应用”和“启动服务”两种职责。
|
|
||||||
|
|
||||||
**Step 2: 新增启动步骤**
|
|
||||||
建议新增:
|
|
||||||
- `START_CMSP_CMTP`
|
|
||||||
- `START_NGINX`
|
|
||||||
- `POST_CHECK`
|
|
||||||
|
|
||||||
**Step 3: 定义启动顺序**
|
|
||||||
推荐顺序:
|
|
||||||
1. 参数校验
|
|
||||||
2. 渲染配置和 SQL
|
|
||||||
3. 准备 license
|
|
||||||
4. 初始化 RabbitMQ / TLQ
|
|
||||||
5. 初始化数据库
|
|
||||||
6. 下发 CMSP / CMTP 配置
|
|
||||||
7. 下发 Nginx / Web 配置
|
|
||||||
8. 启动 CMSP / CMTP
|
|
||||||
9. 启动 Nginx
|
|
||||||
10. 验收检查
|
|
||||||
|
|
||||||
### Task 7: 建立失败边界和输出物
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
|
|
||||||
**Step 1: 明确失败即停边界**
|
|
||||||
- MQ 初始化失败后停止后续步骤
|
|
||||||
- 数据库导入失败后不启动应用
|
|
||||||
- 应用配置失败后不覆盖旧版本
|
|
||||||
- Web 发布失败不影响已启动后台服务
|
|
||||||
|
|
||||||
**Step 2: 输出四类审计产物**
|
|
||||||
每次部署任务至少输出:
|
|
||||||
- 渲染后的配置快照
|
|
||||||
- 渲染后的 SQL 包
|
|
||||||
- 步骤执行日志
|
|
||||||
- 最终部署结果摘要
|
|
||||||
|
|
||||||
### Task 8: 第一批高收益实施顺序
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: 第一优先级**
|
|
||||||
- 标准版 SQL 渲染输出物
|
|
||||||
- DB_INIT 拆分为渲染与执行
|
|
||||||
- 数据库导入结果可审计化
|
|
||||||
|
|
||||||
**Step 2: 第二优先级**
|
|
||||||
- CMSP / CMTP / filetrans 配置输出物
|
|
||||||
- RabbitMQ / TLQ 初始化后的验收
|
|
||||||
|
|
||||||
**Step 3: 第三优先级**
|
|
||||||
- Nginx / Web 渲染与发布
|
|
||||||
- 显式启动顺序和启动后检查
|
|
||||||
|
|
||||||
### Task 9: 验收标准
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(企业信创版)-V1.3.2.pdf`
|
|
||||||
|
|
||||||
**Step 1: 参数层验收**
|
|
||||||
确认后端输入能完整覆盖初始化阶段真正需要的客户化字段,特别是:
|
|
||||||
- 支持方式
|
|
||||||
- 组织名称
|
|
||||||
- Nginx/Web 所需字段
|
|
||||||
- RabbitMQ 通道账号密码
|
|
||||||
|
|
||||||
**Step 2: 配置层验收**
|
|
||||||
确认输出物中不再残留以下占位符:
|
|
||||||
- `AAAABBBBXXX`
|
|
||||||
- `sptp.01app.ip`
|
|
||||||
- `sptp.02app.ip`
|
|
||||||
- `sptp.01db.ip`
|
|
||||||
- `01tlq.ip`
|
|
||||||
- `02tlq.ip`
|
|
||||||
- `mybiccode`
|
|
||||||
- `mycipsid`
|
|
||||||
- `myleicode`
|
|
||||||
|
|
||||||
**Step 3: 部署层验收**
|
|
||||||
确认:
|
|
||||||
- MQ / TLQ 正常可连
|
|
||||||
- TiDB 库和 schema 正常创建
|
|
||||||
- CMSP / CMTP 正常启动
|
|
||||||
- Nginx 正常代理
|
|
||||||
- Web 首页可访问
|
|
||||||
- `organization.json` 为客户实际机构名称
|
|
||||||
|
|
||||||
### Task 10: 非目标项
|
|
||||||
|
|
||||||
**Step 1: 明确本轮不做**
|
|
||||||
以下内容不作为本轮主线:
|
|
||||||
- 大规模直接修改 vendor 原始脚本
|
|
||||||
- 修改介质 readme/document 作为交付主成果
|
|
||||||
- 将所有 cpconfig 依赖一次性彻底移除
|
|
||||||
- 将平台级凭据纳入初始化接口输入
|
|
||||||
|
|
||||||
**Step 2: 后续演进原则**
|
|
||||||
优先让 TMS 接管“产物和编排”,再逐步削弱 vendor shell 的模板职责。
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
# Standard DB Render Apply Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** 将标准版初始化中的数据库步骤从黑盒 `DB_INIT` 拆分为 `DB_RENDER` 和 `DB_APPLY`,生成可审计的 SQL 输出物,并保留数据库凭据在预制层处理。
|
|
||||||
|
|
||||||
**Architecture:** 标准版步骤编排改为先在 task staging 目录生成渲染后的 SQL 包,再由单独的 `DB_APPLY` 步骤将 SQL 包落位到标准收发器数据库加载目录,并按预置命令执行导库。渲染逻辑直接基于 `sql_script_tmp` 模板和 `CMEP-DML.sql/CMEP.sql`,不依赖 vendor 脚本副作用,也不修改 vendor 原始介质。
|
|
||||||
|
|
||||||
**Tech Stack:** Java 17, Spring Boot 3.5, Jackson, JUnit 5, Maven
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: 固化步骤编排与计划文档
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-standard-db-render-apply-plan.md`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
在 `InitServiceTest` 增加标准版断言:
|
|
||||||
- `ENTERPRISE + RABBITMQ` 不再包含 `DB_INIT`
|
|
||||||
- 改为包含 `DB_RENDER` 和 `DB_APPLY`
|
|
||||||
- `ENTERPRISE + TLQ`、`INDIRECT + RABBITMQ`、`INDIRECT + RABBITMQ_TLQ` 同样断言
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: FAIL,提示仍存在 `DB_INIT` 或缺少 `DB_RENDER/DB_APPLY`
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
修改 `InitService.defaultSteps()` 与 `step-command-profiles.json`:
|
|
||||||
- 标准版统一把 `DB_INIT` 替换成 `DB_RENDER`、`DB_APPLY`
|
|
||||||
- 直参版保持 `DB_INIT`
|
|
||||||
- 标准版 `DB_RENDER` 使用 `internal::db_render`
|
|
||||||
- 标准版 `DB_APPLY` 使用 `internal::db_apply`
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 2: 先写标准版 SQL 渲染失败用例
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
新增两个执行器测试:
|
|
||||||
- `shouldRenderStandardDatabaseSqlPackageForEnterpriseRabbitmq`
|
|
||||||
- 在临时目录准备 `cpconfig.cfg`、`sql_script/CMEP-DML.sql`、`sql_script/CMEP.sql`、`sql_script/SCHEMA-DDL.sql`、`sql_script/UP-ORG-INFO.sql`、`sql_script/sql_script_tmp/CMTP-01-raq.sql`
|
|
||||||
- 执行 `internal::db_render`
|
|
||||||
- 断言 staging 下存在 `db/sql/CMTP-01.sql`、`CMEP-DML.sql`、`CMEP.sql` 等文件
|
|
||||||
- 断言 `AAAABBBBXXX`、`01tlq.ip`、`02tlq.ip`、`sptp.01app.ip` 被替换
|
|
||||||
- `shouldApplyStandardDatabaseSqlPackageToLoadDir`
|
|
||||||
- 基于上一步产物执行 `internal::db_apply`
|
|
||||||
- 断言 SQL 被复制到 configured load dir
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: FAIL,提示不支持 `db_render/db_apply` 或目标文件不存在
|
|
||||||
|
|
||||||
**Step 3: Define minimal config surface**
|
|
||||||
|
|
||||||
为标准版数据库处理增加配置项:
|
|
||||||
- `standard-db-script-base-dir`
|
|
||||||
- `standard-db-load-dir`
|
|
||||||
- `standard-db-apply-command`
|
|
||||||
- `standard-db-entry-sql-file-name`
|
|
||||||
|
|
||||||
并在两个 `application.yml` 中补注释和默认值。
|
|
||||||
|
|
||||||
**Step 4: Re-run focused test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: 仍失败,但失败点只剩未实现逻辑
|
|
||||||
|
|
||||||
### Task 3: 实现标准版 DB_RENDER
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Add internal step dispatch**
|
|
||||||
|
|
||||||
在 `executeInternal()` 新增:
|
|
||||||
- `case "db_render" -> executeStandardDbRender(task, step)`
|
|
||||||
|
|
||||||
**Step 2: Implement render behavior**
|
|
||||||
|
|
||||||
新增最小实现:
|
|
||||||
- 仅对标准版生效;直参版返回 skipped
|
|
||||||
- 从 `standard-db-script-base-dir` 读取:
|
|
||||||
- `sql_script/CMEP-DML.sql`
|
|
||||||
- `sql_script/CMEP.sql`
|
|
||||||
- `sql_script/SCHEMA-DDL.sql`
|
|
||||||
- `sql_script/UP-ORG-INFO.sql`
|
|
||||||
- `sql_script/sql_script_tmp/CMTP-01-raq.sql` 或 `CMTP-01-tlq.sql`
|
|
||||||
- 渲染输出到 `staging/<taskId>/db/sql/`
|
|
||||||
- 输出文件名固定为:
|
|
||||||
- `CMEP-DML.sql`
|
|
||||||
- `CMEP.sql`
|
|
||||||
- `SCHEMA-DDL.sql`
|
|
||||||
- `UP-ORG-INFO.sql`
|
|
||||||
- `CMTP-01.sql`
|
|
||||||
- 渲染规则复用 `buildStandardReplacements()`,并补充 SQL 占位映射:
|
|
||||||
- `AAAABBBBXXX -> orgCode`
|
|
||||||
- `01tlq.ip -> mq_01_ip`
|
|
||||||
- `02tlq.ip -> mq_02_ip`
|
|
||||||
- `sptp.01app.ip -> sptp_01app_ip`
|
|
||||||
- `sptp.02app.ip -> sptp_02app_ip`
|
|
||||||
- `mybiccode/mycipsid/myleicode -> 对应机构号映射`
|
|
||||||
- `CMEP.sql` 里的 `source /home/cmep4i/mysql/loadfilepath/...` 保持不变,不在渲染阶段改路径
|
|
||||||
|
|
||||||
**Step 3: Run render test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldRenderStandardDatabaseSqlPackageForEnterpriseRabbitmq test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 4: 实现标准版 DB_APPLY
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Add internal step dispatch**
|
|
||||||
|
|
||||||
在 `executeInternal()` 新增:
|
|
||||||
- `case "db_apply" -> executeStandardDbApply(task, step)`
|
|
||||||
|
|
||||||
**Step 2: Implement apply behavior**
|
|
||||||
|
|
||||||
最小实现:
|
|
||||||
- 仅对标准版生效;直参版返回 skipped
|
|
||||||
- 从 `staging/<taskId>/db/sql/` 读取渲染后 SQL 包
|
|
||||||
- 复制到 `standard-db-load-dir`
|
|
||||||
- `SIMULATE` 模式只校验 staging 产物存在并返回 success
|
|
||||||
- `LOCAL` 模式:
|
|
||||||
- 若 `standard-db-apply-command` 为空,只做落位并返回 success
|
|
||||||
- 若不为空,则以该命令执行导库,工作目录指向 `standard-db-load-dir`
|
|
||||||
- 成功日志中明确输出 staging 路径、load dir、是否执行导库命令
|
|
||||||
|
|
||||||
**Step 3: Run apply test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldApplyStandardDatabaseSqlPackageToLoadDir test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 5: 全量回归与最小文档同步
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Sync plan wording**
|
|
||||||
|
|
||||||
在重构计划中把 Task 3 结果更新为已实现方向:标准版数据库改为 `DB_RENDER / DB_APPLY`。
|
|
||||||
|
|
||||||
**Step 2: Run targeted tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: Run compile verification**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# Deployment Doc Chinese Localization Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Convert the full TMS deployment manual and deployment-related README sections to Chinese while preserving commands, paths, config keys, and interface names.
|
|
||||||
|
|
||||||
**Architecture:** Keep the existing document structure and only localize human-readable prose. Do not change command examples, file paths, YAML keys, API paths, or script names. Limit the scope to `docs/deployment/tms-deployment.md` and the deployment-related part of `README.md`.
|
|
||||||
|
|
||||||
**Tech Stack:** Markdown documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Localize the deployment manual
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
|
|
||||||
**Step 1: Translate headings and narrative text**
|
|
||||||
|
|
||||||
Convert the deployment manual to Chinese, preserving commands, paths, config keys, API paths, and script names.
|
|
||||||
|
|
||||||
**Step 2: Keep structure and examples stable**
|
|
||||||
|
|
||||||
Do not reorder sections or alter shell/YAML examples except for surrounding explanatory text.
|
|
||||||
|
|
||||||
### Task 2: Localize deployment-related README content
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md`
|
|
||||||
|
|
||||||
**Step 1: Translate deployment entry and notes**
|
|
||||||
|
|
||||||
Convert the deployment guide link, Jar deployment section title, and deployment-related notes to Chinese.
|
|
||||||
|
|
||||||
**Step 2: Avoid unrelated README changes**
|
|
||||||
|
|
||||||
Keep non-deployment sections as-is.
|
|
||||||
|
|
||||||
### Task 3: Consistency review
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Review focused diff**
|
|
||||||
|
|
||||||
Run: `git diff -- README.md docs/deployment/tms-deployment.md`
|
|
||||||
Expected: only prose localization changes.
|
|
||||||
|
|
||||||
**Step 2: Spot-check for path/config drift**
|
|
||||||
|
|
||||||
Verify commands, paths, config keys, and script names remain unchanged.
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
# File Upload FileId Design
|
|
||||||
|
|
||||||
**Date:** 2026-03-10
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
为 TMS 提供一个通用文件上传能力,前端在初始化页面选择文件后先上传,后端返回 `fileId`,初始化任务创建和执行阶段继续只引用 `fileId`,不直接传输文件流。
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
本设计只覆盖:
|
|
||||||
- 通用文件上传接口
|
|
||||||
- 文件元信息记录
|
|
||||||
- 与 CISD 初始化的 `fileId` 约定
|
|
||||||
- 前端调用时序
|
|
||||||
|
|
||||||
本设计不覆盖:
|
|
||||||
- 文件下载
|
|
||||||
- 文件删除回收
|
|
||||||
- 秒传/去重
|
|
||||||
- 文件内容级业务校验
|
|
||||||
- 初始化主流程改造
|
|
||||||
|
|
||||||
## Current State
|
|
||||||
|
|
||||||
当前初始化接口:
|
|
||||||
- `/api/v1/init/preview`
|
|
||||||
- `/api/v1/init/tasks`
|
|
||||||
|
|
||||||
都只接收 JSON `InitPreviewRequest`,不接收 `multipart/form-data`。
|
|
||||||
|
|
||||||
当前初始化模块已经完整依赖以下 `fileId` 字段:
|
|
||||||
- `licenses.receiverLicenseFileId`
|
|
||||||
- `licenses.cfgZipFileId`
|
|
||||||
- `mq.tlqLicenseFileId`
|
|
||||||
- `mq.cfmqConfigFileId`
|
|
||||||
|
|
||||||
当前执行器通过 `upload-base-dir/<fileId>` 或 `upload-base-dir/<fileId>/<preferredFileName>` 解析文件。
|
|
||||||
|
|
||||||
## Design Choice
|
|
||||||
|
|
||||||
采用:`通用上传接口 + 初始化继续引用 fileId`
|
|
||||||
|
|
||||||
不采用:`初始化任务接口直接接收 MultipartFile`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 初始化主流程已经基于 `fileId`,继续沿用改动最小
|
|
||||||
- 上传与初始化创建失败语义不同,拆分更清晰
|
|
||||||
- 通用上传能力后续可被证书、升级、备份等模块复用
|
|
||||||
|
|
||||||
## API Design
|
|
||||||
|
|
||||||
### 1. Upload API
|
|
||||||
|
|
||||||
`POST /api/v1/files/upload`
|
|
||||||
|
|
||||||
Content-Type:`multipart/form-data`
|
|
||||||
|
|
||||||
表单字段:
|
|
||||||
- `file`: 必填,文件本体
|
|
||||||
- `bizType`: 可选,默认 `GENERIC`
|
|
||||||
|
|
||||||
返回示例:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"code": 200,
|
|
||||||
"msg": "success",
|
|
||||||
"data": {
|
|
||||||
"fileId": "f_20260310_ab12cd34",
|
|
||||||
"bizType": "INIT",
|
|
||||||
"originalFilename": "cmep.license",
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"size": 2048,
|
|
||||||
"storagePath": "/home/tms/uploads/f_20260310_ab12cd34/cmep.license"
|
|
||||||
},
|
|
||||||
"timestamp": 1741600000000,
|
|
||||||
"traceId": "xxx"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. File Detail API
|
|
||||||
|
|
||||||
`GET /api/v1/files/{fileId}`
|
|
||||||
|
|
||||||
用于页面回显和排障,不参与初始化主链路。
|
|
||||||
|
|
||||||
## Storage Design
|
|
||||||
|
|
||||||
### Storage root
|
|
||||||
|
|
||||||
- `/home/tms/uploads`
|
|
||||||
|
|
||||||
### Directory layout
|
|
||||||
|
|
||||||
- `/home/tms/uploads/<fileId>/`
|
|
||||||
- `/home/tms/uploads/<fileId>/<originalFilename>`
|
|
||||||
|
|
||||||
这样做的原因:
|
|
||||||
- 与当前执行器解析逻辑兼容
|
|
||||||
- 保留原始文件名,便于排查
|
|
||||||
- 每个 `fileId` 单独目录,避免同名覆盖
|
|
||||||
|
|
||||||
## Database Design
|
|
||||||
|
|
||||||
新增表:`sys_file_record`
|
|
||||||
|
|
||||||
字段建议:
|
|
||||||
- `id` bigint pk
|
|
||||||
- `file_id` varchar(128) unique not null
|
|
||||||
- `biz_type` varchar(32) not null
|
|
||||||
- `original_filename` varchar(256) not null
|
|
||||||
- `stored_filename` varchar(256) not null
|
|
||||||
- `storage_path` varchar(512) not null
|
|
||||||
- `content_type` varchar(128) null
|
|
||||||
- `file_size` bigint not null
|
|
||||||
- `sha256` varchar(64) null
|
|
||||||
- `status` varchar(16) not null
|
|
||||||
- `create_time` datetime not null
|
|
||||||
- `update_time` datetime not null
|
|
||||||
|
|
||||||
状态值当前只需要:
|
|
||||||
- `ACTIVE`
|
|
||||||
- `DELETED`
|
|
||||||
|
|
||||||
## Backend Module Layout
|
|
||||||
|
|
||||||
新增模块:
|
|
||||||
|
|
||||||
```text
|
|
||||||
src/main/java/com/cisd/tms/modules/file
|
|
||||||
├── controller/internal
|
|
||||||
│ └── FileInternalController.java
|
|
||||||
├── dto
|
|
||||||
│ ├── FileUploadResponse.java
|
|
||||||
│ └── FileDetailResponse.java
|
|
||||||
├── entity
|
|
||||||
│ └── FileRecordEntity.java
|
|
||||||
├── repository
|
|
||||||
│ └── FileRecordRepository.java
|
|
||||||
└── service
|
|
||||||
└── FileService.java
|
|
||||||
```
|
|
||||||
|
|
||||||
资源文件:
|
|
||||||
|
|
||||||
```text
|
|
||||||
src/main/resources/mapper/file/FileRecordMapper.xml
|
|
||||||
src/main/resources/db/migration/V3__create_sys_file_record.sql
|
|
||||||
```
|
|
||||||
|
|
||||||
## Validation Boundary
|
|
||||||
|
|
||||||
### Upload API validates
|
|
||||||
|
|
||||||
- 文件非空
|
|
||||||
- 原始文件名非空
|
|
||||||
- 文件大小不超过配置上限
|
|
||||||
- `bizType` 枚举合法
|
|
||||||
|
|
||||||
### Init API continues to validate
|
|
||||||
|
|
||||||
- `fileId` 格式
|
|
||||||
- 按版本和 `mqType` 的必填规则
|
|
||||||
- 执行阶段按 `fileId` 是否能找到对应文件
|
|
||||||
|
|
||||||
## Frontend Flow
|
|
||||||
|
|
||||||
1. 用户在初始化页面选择文件
|
|
||||||
2. 前端立即调用上传接口
|
|
||||||
3. 上传成功后拿到 `fileId`
|
|
||||||
4. 前端将 `fileId` 保存到表单状态
|
|
||||||
5. 用户点击“预检”或“创建任务”时,仅提交 JSON
|
|
||||||
|
|
||||||
字段映射:
|
|
||||||
- 收发器 license -> `licenses.receiverLicenseFileId`
|
|
||||||
- TLQ 配置/许可证 -> `mq.tlqLicenseFileId`
|
|
||||||
- CFMQ 配置 -> `mq.cfmqConfigFileId`
|
|
||||||
- 直参 cfg 包 -> `licenses.cfgZipFileId`
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
建议新增:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tms:
|
|
||||||
file:
|
|
||||||
upload-base-dir: /home/tms/uploads
|
|
||||||
max-file-size-mb: 50
|
|
||||||
```
|
|
||||||
|
|
||||||
后续可考虑让初始化执行器复用同一配置根,而不是再单独维护一份路径配置。
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
1. 当前初始化执行器已有 `tms.init.executor.upload-base-dir`,如果新增 `tms.file.upload-base-dir` 而两者不一致,会导致上传成功但执行阶段找不到文件。
|
|
||||||
2. 如果上传接口只保留原始文件名而不做额外清洗,需要限制危险文件名字符。
|
|
||||||
3. 目前不做业务文件类型校验,上传成功不代表该文件一定适合初始化使用。
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
先实现最小闭环:
|
|
||||||
- 上传接口
|
|
||||||
- 查询接口
|
|
||||||
- 文件元信息表
|
|
||||||
- 与初始化 `fileId` 流程对齐
|
|
||||||
|
|
||||||
不在第一版加入:
|
|
||||||
- 下载
|
|
||||||
- 删除
|
|
||||||
- 清理任务
|
|
||||||
- 哈希去重
|
|
||||||
- 扩展名白名单
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
# File Upload FileId Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Add a reusable file upload module that stores uploaded files under `/home/tms/uploads`, returns `fileId`, and keeps CISD initialization flowing through existing `fileId` fields.
|
|
||||||
|
|
||||||
**Architecture:** Introduce a small `modules/file` module with internal upload and query APIs, one metadata table, and a service that owns fileId generation plus filesystem persistence. Keep the init module unchanged at the API boundary except for sharing the same upload storage root and documenting the front-end workflow.
|
|
||||||
|
|
||||||
**Tech Stack:** Spring Boot MVC multipart upload, MyBatis-Plus repository pattern, Flyway SQL migration, JUnit 5
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Add file upload persistence contract
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/db/migration/V3__create_sys_file_record.sql`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/mapper/file/FileRecordMapper.xml`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add a test that expects file metadata to be persisted with:
|
|
||||||
- generated `fileId`
|
|
||||||
- original file name
|
|
||||||
- absolute storage path
|
|
||||||
- `ACTIVE` status
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test`
|
|
||||||
Expected: FAIL because file module classes and table mapping do not exist.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Implement the entity, mapper/repository, and migration with only the fields needed by upload/query.
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add src/main/resources/db/migration/V3__create_sys_file_record.sql \
|
|
||||||
src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java \
|
|
||||||
src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java \
|
|
||||||
src/main/resources/mapper/file/FileRecordMapper.xml \
|
|
||||||
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
|
|
||||||
git commit -m "feat: add file upload persistence contract"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 2: Implement upload service
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/service/FileService.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add tests that assert:
|
|
||||||
- uploaded file is saved under `<upload-base-dir>/<fileId>/<originalFilename>`
|
|
||||||
- blank file upload is rejected
|
|
||||||
- oversize upload is rejected
|
|
||||||
- returned DTO contains `fileId`, size, storagePath
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileServiceTest test`
|
|
||||||
Expected: FAIL because service and properties do not exist.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Implement:
|
|
||||||
- `fileId` generation
|
|
||||||
- file name sanitization
|
|
||||||
- directory creation
|
|
||||||
- file save
|
|
||||||
- metadata insert
|
|
||||||
- detail query by `fileId`
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileServiceTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add src/main/java/com/cisd/tms/modules/file/service/FileService.java \
|
|
||||||
src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java \
|
|
||||||
src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java \
|
|
||||||
src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java \
|
|
||||||
src/main/resources/application.yml config/application.yml.example \
|
|
||||||
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
|
|
||||||
git commit -m "feat: implement file upload service"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 3: Expose internal file APIs
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add controller tests for:
|
|
||||||
- `POST /api/v1/files/upload`
|
|
||||||
- `GET /api/v1/files/{fileId}`
|
|
||||||
|
|
||||||
Verify upload uses multipart, returns `ApiResponse`, and query returns stored metadata.
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest test`
|
|
||||||
Expected: FAIL because controller does not exist.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Expose two endpoints only:
|
|
||||||
- upload
|
|
||||||
- detail query
|
|
||||||
|
|
||||||
Keep them internal-only under `/api/v1/files`.
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java \
|
|
||||||
src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java \
|
|
||||||
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
|
|
||||||
git commit -m "feat: expose internal file upload api"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 4: Align init module with shared upload root and docs
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add or update tests to assert:
|
|
||||||
- init executor upload root matches the shared upload root config
|
|
||||||
- docs clearly state init APIs accept `fileId`, not multipart files
|
|
||||||
- README documents front-end flow: upload first, then create init task
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test`
|
|
||||||
Expected: FAIL because docs/config are not aligned yet.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Align configuration and docs without changing init request DTO semantics.
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java \
|
|
||||||
src/main/resources/application.yml config/application.yml.example \
|
|
||||||
docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json README.md \
|
|
||||||
src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java
|
|
||||||
git commit -m "docs: align init fileId flow with upload api"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 5: Add upload API OpenAPI spec
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add a documentation test or assertion that the upload route and response fields are present in the OpenAPI output.
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test`
|
|
||||||
Expected: FAIL because the route is not documented yet.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Document:
|
|
||||||
- upload API
|
|
||||||
- query API
|
|
||||||
- multipart request
|
|
||||||
- `fileId` response
|
|
||||||
- init API references to upload-first workflow
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json \
|
|
||||||
src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java
|
|
||||||
git commit -m "docs: add file upload api spec"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 6: Final verification
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Run file module tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileServiceTest,FileInternalControllerTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 2: Run init-related tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: Run compile**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Review focused diff**
|
|
||||||
|
|
||||||
Run: `git diff -- src/main/java/com/cisd/tms/modules/file src/main/resources/db/migration/V3__create_sys_file_record.sql src/main/resources/mapper/file src/main/resources/application.yml config/application.yml.example README.md docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json`
|
|
||||||
Expected: only file upload module, config, README, and OpenAPI/doc alignment changes.
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
# Init Execute Async Resume Design
|
|
||||||
|
|
||||||
**Date:** 2026-03-10
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
解决初始化执行接口同步阻塞导致的请求超时问题,并支持任务在失败后从第一个未成功步骤继续执行,而不是每次都从头开始。
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
本设计覆盖:
|
|
||||||
- `/api/v1/init/tasks/{taskId}/execute` 改为异步受理
|
|
||||||
- 初始化任务后台执行模型
|
|
||||||
- 步骤级断点续跑规则
|
|
||||||
- 同一任务的重复触发保护
|
|
||||||
- 现有查询接口与状态语义调整
|
|
||||||
|
|
||||||
本设计不覆盖:
|
|
||||||
- 分布式任务调度
|
|
||||||
- 多实例间执行协调
|
|
||||||
- 服务重启后的自动恢复调度
|
|
||||||
- 新增前端页面
|
|
||||||
- 初始化步骤编排本身的变更
|
|
||||||
|
|
||||||
## Current State
|
|
||||||
|
|
||||||
当前执行入口是同步的:
|
|
||||||
- 控制器直接调用 `InitService.executeTask(taskId)`
|
|
||||||
- 服务层在请求线程内串行执行全部步骤
|
|
||||||
- 任一步骤失败后立刻中断
|
|
||||||
|
|
||||||
当前问题有两个:
|
|
||||||
- 任务执行时间较长时,HTTP 请求容易超时
|
|
||||||
- 再次执行时没有跳过已成功步骤的逻辑,会从第一步重新开始
|
|
||||||
|
|
||||||
当前已有可复用基础:
|
|
||||||
- 任务主表 `tms_init_task`
|
|
||||||
- 任务步骤表 `tms_init_task_step`
|
|
||||||
- 步骤状态字段:`PENDING` / `RUNNING` / `SUCCESS` / `FAILED`
|
|
||||||
- 现有步骤详情和日志查询接口
|
|
||||||
|
|
||||||
## Design Choice
|
|
||||||
|
|
||||||
采用:`应用内异步执行 + 基于步骤状态续跑`
|
|
||||||
|
|
||||||
不采用:`继续同步执行`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 无法避免请求超时
|
|
||||||
- 与实际长耗时初始化场景不匹配
|
|
||||||
|
|
||||||
不采用:`数据库任务队列 + 独立 worker`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 当前需求重点是先解决超时和重跑问题
|
|
||||||
- 现阶段引入完整调度系统成本过高
|
|
||||||
|
|
||||||
## API Design
|
|
||||||
|
|
||||||
### Execute API
|
|
||||||
|
|
||||||
`POST /api/v1/init/tasks/{taskId}/execute`
|
|
||||||
|
|
||||||
接口语义调整为:
|
|
||||||
- 只负责受理执行请求
|
|
||||||
- 不等待全部步骤完成
|
|
||||||
- 返回当前任务快照
|
|
||||||
|
|
||||||
返回字段继续复用 `InitTaskExecuteResponse`,但语义变为:
|
|
||||||
- `taskId`: 任务号
|
|
||||||
- `status`: 受理后的当前状态,通常为 `RUNNING`
|
|
||||||
- `totalSteps`: 总步骤数
|
|
||||||
- `successSteps`: 当前已成功步骤数
|
|
||||||
|
|
||||||
前端后续继续通过以下接口轮询:
|
|
||||||
- `GET /api/v1/init/tasks/{taskId}`
|
|
||||||
- `GET /api/v1/init/tasks/{taskId}/steps`
|
|
||||||
- `GET /api/v1/init/tasks/{taskId}/steps/{stepNo}/log`
|
|
||||||
|
|
||||||
## Execution Model
|
|
||||||
|
|
||||||
### 1. Request thread
|
|
||||||
|
|
||||||
请求线程只做以下事情:
|
|
||||||
- 校验任务存在且有步骤
|
|
||||||
- 检查是否已经在执行中
|
|
||||||
- 将任务状态置为 `RUNNING`
|
|
||||||
- 提交后台执行任务
|
|
||||||
- 立即返回
|
|
||||||
|
|
||||||
### 2. Background worker
|
|
||||||
|
|
||||||
后台线程负责真正串行执行步骤:
|
|
||||||
- 重新加载任务与步骤
|
|
||||||
- 识别续跑起点
|
|
||||||
- 逐步执行
|
|
||||||
- 每步结束后立刻落库状态、消息、日志路径、退出码
|
|
||||||
- 汇总任务最终状态
|
|
||||||
|
|
||||||
### 3. Single-task guard
|
|
||||||
|
|
||||||
同一 `taskId` 在一个应用实例内只允许一个执行线程:
|
|
||||||
- 若任务已在本实例执行中,再次调用 `execute` 不再重复启动
|
|
||||||
- 接口直接返回当前快照
|
|
||||||
|
|
||||||
实现上可使用进程内 `ConcurrentHashMap<String, Future<?>>` 或等价结构维护活动任务。
|
|
||||||
|
|
||||||
## Resume Rule
|
|
||||||
|
|
||||||
再次执行时采用以下规则:
|
|
||||||
|
|
||||||
1. 所有 `SUCCESS` 步骤直接跳过,不重跑
|
|
||||||
2. 从第一个非 `SUCCESS` 步骤开始继续
|
|
||||||
3. 后续步骤按原顺序执行
|
|
||||||
4. 若本次再次失败,当前失败步骤状态记为 `FAILED`,任务状态记为 `FAILED`
|
|
||||||
|
|
||||||
### RUNNING residue handling
|
|
||||||
|
|
||||||
如果上一次执行过程中服务异常退出,可能残留 `RUNNING` 步骤。
|
|
||||||
|
|
||||||
本设计约定:
|
|
||||||
- 新一轮执行开始前,将残留 `RUNNING` 步骤视为未完成
|
|
||||||
- 统一重置为 `FAILED`
|
|
||||||
- 续跑时从第一个非 `SUCCESS` 步骤开始
|
|
||||||
|
|
||||||
这样可以保留“上次停在这里”的事实,并避免把 `RUNNING` 误判为仍在健康执行。
|
|
||||||
|
|
||||||
## Status Semantics
|
|
||||||
|
|
||||||
### Task status
|
|
||||||
|
|
||||||
- `PENDING`: 任务已创建,尚未开始
|
|
||||||
- `RUNNING`: 已受理且后台执行中
|
|
||||||
- `SUCCESS`: 全部步骤成功
|
|
||||||
- `FAILED`: 某一步失败并已停止
|
|
||||||
|
|
||||||
### Step status
|
|
||||||
|
|
||||||
- `PENDING`: 从未执行
|
|
||||||
- `RUNNING`: 当前正在执行
|
|
||||||
- `SUCCESS`: 已成功,后续重试跳过
|
|
||||||
- `FAILED`: 最近一次执行失败,后续重试从此处继续
|
|
||||||
|
|
||||||
## Concurrency Policy
|
|
||||||
|
|
||||||
### Same task
|
|
||||||
|
|
||||||
同一任务重复点击执行:
|
|
||||||
- 若本实例检测到该任务已在执行,直接返回当前状态
|
|
||||||
- 不再启动第二个后台线程
|
|
||||||
|
|
||||||
### Different tasks
|
|
||||||
|
|
||||||
不同任务是否允许并发执行,第一版保持当前默认:
|
|
||||||
- 允许不同 `taskId` 并行受理
|
|
||||||
- 不额外加全局串行锁
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 当前需求只明确要求单任务避免重入
|
|
||||||
- 是否需要全局串行,取决于目标主机资源和脚本互斥关系,后续再单独设计
|
|
||||||
|
|
||||||
## Data Changes
|
|
||||||
|
|
||||||
本设计优先复用现有表结构,不新增表字段。
|
|
||||||
|
|
||||||
依赖现有字段即可表达:
|
|
||||||
- 任务当前状态
|
|
||||||
- 步骤当前状态
|
|
||||||
- 失败消息
|
|
||||||
- 日志路径
|
|
||||||
- 退出码
|
|
||||||
|
|
||||||
## Testing Strategy
|
|
||||||
|
|
||||||
需要补的测试重点:
|
|
||||||
|
|
||||||
1. 异步受理
|
|
||||||
- `execute` 调用应快速返回
|
|
||||||
- 后台线程继续推进步骤状态
|
|
||||||
|
|
||||||
2. 失败后续跑
|
|
||||||
- 首次执行在某步失败
|
|
||||||
- 再次执行时跳过已 `SUCCESS` 步骤
|
|
||||||
- 从失败步骤重新执行并继续后续步骤
|
|
||||||
|
|
||||||
3. 残留 `RUNNING`
|
|
||||||
- 构造上一次异常中断留下的 `RUNNING` 步骤
|
|
||||||
- 重试时应从该步骤继续
|
|
||||||
|
|
||||||
4. 单任务重复触发保护
|
|
||||||
- 同一个 `taskId` 在执行中再次调用
|
|
||||||
- 不应重复启动第二个执行线程
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
1. 应用内异步执行依赖当前进程存活,若服务重启,运行中的任务不会自动恢复。
|
|
||||||
2. 若底层初始化脚本本身不具备完全幂等性,虽然步骤级跳过已成功步骤可以减少重复执行,但失败步骤重试仍可能触发环境冲突。
|
|
||||||
3. 当前只做单实例内去重;若后续部署多实例,需要补分布式锁或数据库抢占机制。
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
先实现最小闭环:
|
|
||||||
- `execute` 异步受理
|
|
||||||
- 单任务进程内防重入
|
|
||||||
- 从第一个非 `SUCCESS` 步骤续跑
|
|
||||||
- 残留 `RUNNING` 视为失败点恢复
|
|
||||||
|
|
||||||
不在第一版加入:
|
|
||||||
- 分布式调度
|
|
||||||
- 自动恢复未完成任务
|
|
||||||
- 新状态枚举或额外任务队列表
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
# Init Execute Async Resume Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Make `/api/v1/init/tasks/{taskId}/execute` return immediately after accepting work, then run init steps in the background and resume from the first non-`SUCCESS` step on retry.
|
|
||||||
|
|
||||||
**Architecture:** Keep the existing task table and step table as the source of truth. Split `InitService.executeTask` into an accept-and-dispatch path plus a background execution path, and use existing step statuses to determine where to resume. Add a lightweight in-process guard so one `taskId` cannot be started twice concurrently in the same application instance.
|
|
||||||
|
|
||||||
**Tech Stack:** Spring Boot service/controller layer, Java concurrency utilities, MyBatis-style repositories already present in the module, JUnit 5
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Lock down current behavior with service tests
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing tests**
|
|
||||||
|
|
||||||
Add tests that assert:
|
|
||||||
- `executeTask(taskId)` returns before a deliberately blocking executor finishes all steps
|
|
||||||
- retry skips steps already marked `SUCCESS` and resumes from the first `FAILED` step
|
|
||||||
- residual `RUNNING` steps are treated as the resume point on retry
|
|
||||||
- duplicate execute calls for the same running task do not launch a second execution
|
|
||||||
|
|
||||||
**Step 2: Run tests to verify they fail**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test`
|
|
||||||
Expected: FAIL because execution is still synchronous and always starts from step 1.
|
|
||||||
|
|
||||||
**Step 3: Write minimal test scaffolding**
|
|
||||||
|
|
||||||
Extend the in-memory executor/repository helpers in the test file so they can:
|
|
||||||
- block on a latch or sleep
|
|
||||||
- count executed step codes
|
|
||||||
- fail a chosen step once and succeed on retry
|
|
||||||
|
|
||||||
Do not change production code in this step.
|
|
||||||
|
|
||||||
**Step 4: Run tests to verify RED is stable**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test`
|
|
||||||
Expected: FAIL with assertion mismatches that prove the new behavior is not implemented yet.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 2: Introduce async dispatch in `InitService`
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Implement minimal async acceptance path**
|
|
||||||
|
|
||||||
Refactor `InitService` so `executeTask(taskId)`:
|
|
||||||
- loads task and steps
|
|
||||||
- returns a snapshot response quickly
|
|
||||||
- submits real work to a background executor
|
|
||||||
|
|
||||||
Use a small in-process dispatcher owned by `InitService`:
|
|
||||||
- `ExecutorService` or equivalent
|
|
||||||
- active-task map keyed by `taskId`
|
|
||||||
|
|
||||||
**Step 2: Keep the real execution logic in a dedicated method**
|
|
||||||
|
|
||||||
Create a private method such as `executeTaskInBackground(taskId)` that:
|
|
||||||
- reloads task and steps from repository
|
|
||||||
- updates statuses
|
|
||||||
- runs steps serially
|
|
||||||
- persists each step result immediately
|
|
||||||
- updates final task status
|
|
||||||
|
|
||||||
**Step 3: Run focused tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Refactor for readability**
|
|
||||||
|
|
||||||
Extract helpers only if needed:
|
|
||||||
- build response snapshot
|
|
||||||
- mark task running
|
|
||||||
- remove active-task entry in `finally`
|
|
||||||
|
|
||||||
Do not add extra features.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 3: Implement resume-from-first-non-success semantics
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Implement step selection logic**
|
|
||||||
|
|
||||||
Before running steps in the background:
|
|
||||||
- convert residual `RUNNING` steps to `FAILED`
|
|
||||||
- skip every step already marked `SUCCESS`
|
|
||||||
- start execution at the first non-`SUCCESS` step
|
|
||||||
|
|
||||||
Preserve current semantics after the resume point:
|
|
||||||
- mark current step `RUNNING`
|
|
||||||
- on success mark `SUCCESS`
|
|
||||||
- on failure mark `FAILED` and stop
|
|
||||||
|
|
||||||
**Step 2: Preserve response counters**
|
|
||||||
|
|
||||||
Ensure `successSteps` in `InitTaskExecuteResponse` reflects the current number of successful steps, including successes from earlier runs.
|
|
||||||
|
|
||||||
**Step 3: Run focused tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Run the earlier async tests again**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 4: Align controller and API-facing semantics
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
|
|
||||||
**Step 1: Make the API comments and DTO semantics match async behavior**
|
|
||||||
|
|
||||||
Update JavaDoc/comments so they describe:
|
|
||||||
- execute endpoint only accepts and starts background work
|
|
||||||
- polling should use existing detail/step/log APIs
|
|
||||||
|
|
||||||
If needed, add a field only if tests prove it is necessary. Prefer reusing the current DTO unchanged.
|
|
||||||
|
|
||||||
**Step 2: Run focused verification**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: PASS for all service tests, including the pre-existing create/query/execute cases.
|
|
||||||
|
|
||||||
**Step 3: Review the controller surface**
|
|
||||||
|
|
||||||
Check that:
|
|
||||||
- route path stays unchanged
|
|
||||||
- response wrapper stays unchanged
|
|
||||||
- no new endpoint is introduced unnecessarily
|
|
||||||
|
|
||||||
**Step 4: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 5: Final verification
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Run init service tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 2: Run init executor regression tests touched by earlier behavior changes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldInjectDatabaseCredentialsWhenExecutingStandardDbApplyCommand,ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates,ConfigurableInitStepExecutorTest#shouldStartStandardCmspCmtpWithConfiguredCommand test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: Run compile**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Review focused diff**
|
|
||||||
|
|
||||||
Run: `git diff -- src/main/java/com/cisd/tms/modules/init/service/InitService.java src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java docs/plans/2026-03-10-init-execute-async-resume-design.md docs/plans/2026-03-10-init-execute-async-resume-plan.md`
|
|
||||||
Expected: only async-dispatch, resume logic, and related documentation changes.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
# Standard Init Script Templates Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Add standard CISD post-init script templates to the repository and document how TMS should reference them after deployment to `/home/tms/bin`.
|
|
||||||
|
|
||||||
**Architecture:** Keep the runtime command model unchanged in TMS. Add script templates under the repository so deployment has a clear source of truth, then point `application.yml.example` and `README.md` to the deployed absolute paths. Tests only verify the repository artifacts and expected command content, not real database or nginx execution.
|
|
||||||
|
|
||||||
**Tech Stack:** Shell scripts, Spring Boot config examples, JUnit 5 filesystem assertions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Add repository script templates
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/apply_standard_db.sh`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/start_standard_apps.sh`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/start_standard_nginx.sh`
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/check_standard_runtime.sh`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add tests that assert the four script files exist in `scripts/standard-init/` and contain the expected key commands:
|
|
||||||
- DB script references `SCHEMA-DDL.sql`, `CMEP.sql`, `UP-ORG-INFO.sql`
|
|
||||||
- App start script references `start_cmsp.sh` and `start_cmtp.sh`
|
|
||||||
- Nginx start script references `/usr/local/nginx/sbin/nginx`
|
|
||||||
- Post-check script references CMSP/CMTP/nginx process checks and `organization.json`
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates test`
|
|
||||||
Expected: FAIL because the scripts do not exist yet.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Create the four scripts with:
|
|
||||||
- `#!/bin/bash`
|
|
||||||
- `set -euo pipefail`
|
|
||||||
- environment variable placeholders for preset credentials where needed
|
|
||||||
- comments limited to critical operational assumptions
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/standard-init src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java
|
|
||||||
git commit -m "feat: add standard init script templates"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 2: Wire deployment-facing config examples
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
Add a test that asserts:
|
|
||||||
- `application.yml.example` points the four command properties to `/home/tms/bin/*.sh`
|
|
||||||
- `README.md` documents the repository source path `scripts/standard-init/` and the target deploy path `/home/tms/bin`
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: FAIL because the docs/config are not updated yet.
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
Update example config and README with:
|
|
||||||
- exact deployed command values
|
|
||||||
- copy/deploy note from `scripts/standard-init/` to `/home/tms/bin`
|
|
||||||
- required environment variables for DB script
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add config/application.yml.example README.md src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java
|
|
||||||
git commit -m "docs: wire standard init script template deployment"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 3: Final verification
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Run focused tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 2: Run init test suite**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: Run compile**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Review git diff**
|
|
||||||
|
|
||||||
Run: `git diff -- scripts/standard-init config/application.yml.example README.md src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
Expected: only script templates, config example, README, and tests changed.
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
# Standard Post Deploy Completion Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** 补齐标准版初始化在部署文档后半段缺失的动作,包括真实导库、CMSP/CMTP 启动与检查、nginx 配置与启动、WEB 发布。
|
|
||||||
|
|
||||||
**Architecture:** 保持“预置层负责基础安装与平台凭据,初始化层负责客户化和运行配置”边界不变。TMS 继续负责生成配置和 SQL 输出物,并在标准版流程中新增后半段步骤:真实导库、应用启动、nginx 配置与启动、WEB 发布、启动后检查。vendor 原始脚本继续只读,优先通过 staging 配置和显式命令编排补齐流程,而不扩散成新的黑盒主导链路。
|
|
||||||
|
|
||||||
**Tech Stack:** Java 17, Spring Boot 3.5, Jackson, JUnit 5, Maven, Shell command orchestration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: 固化标准版后半段步骤编排
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(企业信创版)-V1.3.2.doc`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(间参版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(金融机构信创版)-V1.3.2.doc`
|
|
||||||
|
|
||||||
**Step 1: Write the failing test**
|
|
||||||
|
|
||||||
在 `InitServiceTest` 新增标准版步骤断言:
|
|
||||||
- `ENTERPRISE + RABBITMQ` 包含:`DB_RENDER`、`DB_APPLY`、`DEPLOY_RECEIVER`、`NGINX_CONFIG_APPLY`、`WEB_CONFIG_APPLY`、`START_CMSP_CMTP`、`START_NGINX`、`POST_CHECK`
|
|
||||||
- `ENTERPRISE + TLQ` 同样包含上述后半段步骤
|
|
||||||
- `INDIRECT + RABBITMQ`、`INDIRECT + RABBITMQ_TLQ` 同样断言
|
|
||||||
- 直参版仍不包含这些标准版步骤
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: FAIL,提示步骤未生成
|
|
||||||
|
|
||||||
**Step 3: Write minimal implementation**
|
|
||||||
|
|
||||||
修改 `InitService.defaultSteps()` 和 `step-command-profiles.json`:
|
|
||||||
- 在标准版 `DEPLOY_RECEIVER` 后追加:
|
|
||||||
- `NGINX_CONFIG_APPLY`
|
|
||||||
- `WEB_CONFIG_APPLY`
|
|
||||||
- `START_CMSP_CMTP`
|
|
||||||
- `START_NGINX`
|
|
||||||
- `POST_CHECK`
|
|
||||||
- 命令模板统一先挂到 internal step:
|
|
||||||
- `internal::nginx_config_apply`
|
|
||||||
- `internal::web_config_apply`
|
|
||||||
- `internal::start_cmsp_cmtp`
|
|
||||||
- `internal::start_nginx`
|
|
||||||
- `internal::post_check`
|
|
||||||
|
|
||||||
**Step 4: Run test to verify it passes**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 2: 增加配置面与失败测试
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing tests**
|
|
||||||
|
|
||||||
新增执行器测试:
|
|
||||||
- `shouldApplyStandardNginxConfigFromTemplate`
|
|
||||||
- `shouldPublishStandardWebAssetsAndOrganizationJson`
|
|
||||||
- `shouldStartStandardCmspCmtpWithConfiguredCommand`
|
|
||||||
- `shouldStartStandardNginxWithConfiguredCommand`
|
|
||||||
- `shouldRunStandardPostCheck`
|
|
||||||
|
|
||||||
测试目标:
|
|
||||||
- `NGINX_CONFIG_APPLY` 会输出替换后的 `nginx.conf`
|
|
||||||
- `WEB_CONFIG_APPLY` 会生成 `organization.json` 并发布 `front.zip` 内容
|
|
||||||
- `START_CMSP_CMTP` 会调用预置启动命令或脚本
|
|
||||||
- `START_NGINX` 会调用 nginx 启动命令
|
|
||||||
- `POST_CHECK` 会执行配置的检查命令并记录日志
|
|
||||||
|
|
||||||
**Step 2: Run test to verify it fails**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: FAIL,提示 internal step 未实现或配置缺失
|
|
||||||
|
|
||||||
**Step 3: Define minimal config surface**
|
|
||||||
|
|
||||||
为标准版后半段补齐配置项:
|
|
||||||
- `standard-nginx-template-path`
|
|
||||||
- `standard-nginx-target-path`
|
|
||||||
- `standard-web-front-zip-path`
|
|
||||||
- `standard-web-work-dir`
|
|
||||||
- `standard-web-target-dir`
|
|
||||||
- `standard-web-organization-json-path`
|
|
||||||
- `standard-app-start-command`
|
|
||||||
- `standard-nginx-start-command`
|
|
||||||
- `standard-post-check-command`
|
|
||||||
|
|
||||||
说明:
|
|
||||||
- 真实命令由环境配置注入,TMS 只编排,不硬编码具体 systemd/脚本形态
|
|
||||||
- 默认值可沿用文档建议路径
|
|
||||||
|
|
||||||
**Step 4: Re-run focused test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: 仍失败,但仅剩实现缺失
|
|
||||||
|
|
||||||
### Task 3: 实现标准版 Nginx 配置落地
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/setngx.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/nginx.conf`
|
|
||||||
|
|
||||||
**Step 1: Add internal step dispatch**
|
|
||||||
|
|
||||||
在 `executeInternal()` 新增:
|
|
||||||
- `case "nginx_config_apply" -> executeStandardNginxConfigApply(task, step)`
|
|
||||||
|
|
||||||
**Step 2: Implement minimal behavior**
|
|
||||||
|
|
||||||
实现逻辑:
|
|
||||||
- 仅对标准版生效
|
|
||||||
- 读取 `standard-nginx-template-path`
|
|
||||||
- 复用 `buildStandardReplacements()` 替换 `sptp.01app.ip`、`sptp.02app.ip`
|
|
||||||
- 将渲染结果先输出到 `staging/<taskId>/nginx/nginx.conf`
|
|
||||||
- LOCAL 模式复制到 `standard-nginx-target-path`
|
|
||||||
- SIMULATE 模式仅产出 staging 文件
|
|
||||||
|
|
||||||
**Step 3: Run focused test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldApplyStandardNginxConfigFromTemplate test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 4: 实现标准版 WEB 发布
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setweb.sh`
|
|
||||||
|
|
||||||
**Step 1: Add internal step dispatch**
|
|
||||||
|
|
||||||
在 `executeInternal()` 新增:
|
|
||||||
- `case "web_config_apply" -> executeStandardWebConfigApply(task, step)`
|
|
||||||
|
|
||||||
**Step 2: Implement minimal behavior**
|
|
||||||
|
|
||||||
实现逻辑:
|
|
||||||
- 仅对标准版生效
|
|
||||||
- 从 `standard-web-front-zip-path` 读取 `front.zip`
|
|
||||||
- 解压到 `staging/<taskId>/web/`
|
|
||||||
- 生成 `organization.json`,内容来自 `request.orgNameCn`
|
|
||||||
- LOCAL 模式将解压产物发布到 `standard-web-target-dir`
|
|
||||||
- 同步 `organization.json` 到 `standard-web-organization-json-path`
|
|
||||||
- SIMULATE 模式仅生成 staging 产物
|
|
||||||
|
|
||||||
**Step 3: Run focused test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldPublishStandardWebAssetsAndOrganizationJson test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 5: 实现标准版启动与检查
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sh/sh/stcmep_cent.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/start_cmsp.sh`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmtp/01/start_cmtp.sh`
|
|
||||||
|
|
||||||
**Step 1: Add internal step dispatch**
|
|
||||||
|
|
||||||
在 `executeInternal()` 新增:
|
|
||||||
- `case "start_cmsp_cmtp" -> executeStandardStartApp(task, step)`
|
|
||||||
- `case "start_nginx" -> executeStandardStartNginx(task, step)`
|
|
||||||
- `case "post_check" -> executeStandardPostCheck(task, step)`
|
|
||||||
|
|
||||||
**Step 2: Implement minimal behavior**
|
|
||||||
|
|
||||||
实现逻辑:
|
|
||||||
- `START_CMSP_CMTP`
|
|
||||||
- 仅对标准版生效
|
|
||||||
- 执行 `standard-app-start-command`
|
|
||||||
- `START_NGINX`
|
|
||||||
- 执行 `standard-nginx-start-command`
|
|
||||||
- `POST_CHECK`
|
|
||||||
- 执行 `standard-post-check-command`
|
|
||||||
- 三者都要求:
|
|
||||||
- SIMULATE 模式返回模拟成功
|
|
||||||
- LOCAL 模式走统一 `runCommand` 逻辑
|
|
||||||
- 日志记录命令、cwd、exit code
|
|
||||||
|
|
||||||
**Step 3: Run focused tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldStartStandardCmspCmtpWithConfiguredCommand,ConfigurableInitStepExecutorTest#shouldStartStandardNginxWithConfiguredCommand,ConfigurableInitStepExecutorTest#shouldRunStandardPostCheck test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 6: 将 DB_APPLY 收敛为“真实导库”入口
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Tighten DB_APPLY contract**
|
|
||||||
|
|
||||||
修改 `DB_APPLY` 行为:
|
|
||||||
- 标准版 LOCAL 模式下,如果 `standard-db-apply-command` 为空,直接失败而不是跳过
|
|
||||||
- 错误信息明确提示“导库命令未配置”
|
|
||||||
|
|
||||||
**Step 2: Add test**
|
|
||||||
|
|
||||||
新增测试:
|
|
||||||
- `shouldFailDbApplyWhenStandardDbApplyCommandMissingInLocalMode`
|
|
||||||
- `shouldExecuteStandardDbApplyCommandWhenConfigured`
|
|
||||||
|
|
||||||
**Step 3: Run focused test**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldFailDbApplyWhenStandardDbApplyCommandMissingInLocalMode,ConfigurableInitStepExecutorTest#shouldExecuteStandardDbApplyCommandWhenConfigured test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
### Task 7: 文档同步与回归验证
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Sync plan wording**
|
|
||||||
|
|
||||||
将标准版初始化主链路更新为:
|
|
||||||
- `... -> DB_APPLY -> DEPLOY_RECEIVER -> NGINX_CONFIG_APPLY -> WEB_CONFIG_APPLY -> START_CMSP_CMTP -> START_NGINX -> POST_CHECK -> VERIFY`
|
|
||||||
|
|
||||||
**Step 2: Refresh API/Doc examples if needed**
|
|
||||||
|
|
||||||
如果接口示例中已有步骤说明,补充新增标准版后半段步骤说明。
|
|
||||||
|
|
||||||
**Step 3: Run targeted tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Run compile verification**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
# TMS Deployment Document Design
|
|
||||||
|
|
||||||
**Date:** 2026-03-10
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
维护一份面向现场部署和运维的 TMS 部署手册,覆盖 `/home/tms` 目录结构、jar 与脚本部署、配置文件、初始化依赖、文件上传目录、启动检查与常见故障定位。
|
|
||||||
|
|
||||||
## Audience
|
|
||||||
|
|
||||||
- 现场运维
|
|
||||||
- 集成交付人员
|
|
||||||
- 后端开发/联调人员
|
|
||||||
|
|
||||||
## Document Style
|
|
||||||
|
|
||||||
文档应以“可执行手册”为目标,而不是概念说明。要求:
|
|
||||||
- 直接给目录和命令
|
|
||||||
- 标明哪些内容必须预置,哪些由 TMS 初始化处理
|
|
||||||
- 区分标准版和直参版相关依赖,但不重复解释业务背景
|
|
||||||
- 每节都有输入、操作、结果或检查点
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
纳入部署文档:
|
|
||||||
- TMS 运行环境要求
|
|
||||||
- `/home/tms` 目录结构
|
|
||||||
- jar、配置、脚本、上传目录部署
|
|
||||||
- `application.yml` 关键配置说明
|
|
||||||
- 标准版初始化脚本 `/home/tms/bin/*.sh` 的作用和依赖
|
|
||||||
- 文件上传与 `fileId` 模型说明
|
|
||||||
- TMS 启动、停止、状态检查
|
|
||||||
- 初始化联调前检查
|
|
||||||
- 常见故障与排查
|
|
||||||
|
|
||||||
不纳入:
|
|
||||||
- CIPS 标准收发器基础安装手册全文复述
|
|
||||||
- 密码卡详细使用文档
|
|
||||||
- OpenAPI 业务接口全集说明
|
|
||||||
|
|
||||||
## Proposed Document Location
|
|
||||||
|
|
||||||
建议新增正式手册:
|
|
||||||
- `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
|
|
||||||
README 保留简版入口,完整运维说明进入该文档。
|
|
||||||
|
|
||||||
## Proposed Structure
|
|
||||||
|
|
||||||
1. 文档目的与适用范围
|
|
||||||
2. 环境要求
|
|
||||||
3. 部署目录结构
|
|
||||||
4. 部署物清单
|
|
||||||
5. `/home/tms/config/application.yml` 关键配置
|
|
||||||
6. `/home/tms/bin` 初始化脚本说明
|
|
||||||
7. 文件上传与 `fileId` 约定
|
|
||||||
8. 启动/停止/状态命令
|
|
||||||
9. 初始化前置检查
|
|
||||||
10. 常见故障排查
|
|
||||||
11. 附录:推荐命令与检查项
|
|
||||||
|
|
||||||
## Key Content Decisions
|
|
||||||
|
|
||||||
### 1. 明确边界
|
|
||||||
|
|
||||||
部署文档必须明确:
|
|
||||||
- TMS 只负责自身部署和 CISD 初始化编排
|
|
||||||
- 标准收发器、RabbitMQ、TLQ、TiDB、nginx 的基础安装属于预置层
|
|
||||||
- 初始化阶段负责客户化配置、落位、导库、发布和启动命令调用
|
|
||||||
|
|
||||||
### 2. 目录结构固定化
|
|
||||||
|
|
||||||
文档采用 `/home/tms` 作为标准路径:
|
|
||||||
- `/home/tms/tms-framework.jar`
|
|
||||||
- `/home/tms/config/application.yml`
|
|
||||||
- `/home/tms/scripts/tms.sh`
|
|
||||||
- `/home/tms/bin/*.sh`
|
|
||||||
- `/home/tms/uploads/`
|
|
||||||
- `/home/tms/logs/`
|
|
||||||
- `/home/tms/run/`
|
|
||||||
- `/home/tms/tmp/`
|
|
||||||
|
|
||||||
### 3. 配置说明强调初始化相关参数
|
|
||||||
|
|
||||||
重点说明:
|
|
||||||
- `tms.file.storage.upload-base-dir`
|
|
||||||
- `tms.init.executor.*`
|
|
||||||
- 标准版脚本命令路径
|
|
||||||
- RabbitMQ 预置管理员账号
|
|
||||||
- 日志目录、staging 目录
|
|
||||||
|
|
||||||
### 4. 文件上传模型单独成节
|
|
||||||
|
|
||||||
必须明确:
|
|
||||||
- 初始化接口不接收 multipart 文件
|
|
||||||
- 前端先上传文件,再使用 `fileId`
|
|
||||||
- 上传目录与初始化执行器解析规则保持一致
|
|
||||||
|
|
||||||
### 5. 故障排查按常见现场问题组织
|
|
||||||
|
|
||||||
优先纳入:
|
|
||||||
- jar 无法启动
|
|
||||||
- `DB_APPLY` 命令为空
|
|
||||||
- `cpconfig` 找不到
|
|
||||||
- `fileId` 文件找不到
|
|
||||||
- RabbitMQ 队列创建失败
|
|
||||||
- nginx 未启动
|
|
||||||
- WEB 未发布
|
|
||||||
|
|
||||||
## Output Expectation
|
|
||||||
|
|
||||||
产出两类文档:
|
|
||||||
- `README.md` 中保留精简入口
|
|
||||||
- `docs/deployment/tms-deployment.md` 作为完整部署手册
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
# TMS Deployment Document Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Create a production-oriented TMS deployment manual that documents runtime files, directories, scripts, config, upload/fileId flow, and on-host verification for `/home/tms` deployments.
|
|
||||||
|
|
||||||
**Architecture:** Keep `README.md` as the short entry point and move the full operational content into a dedicated deployment manual under `docs/deployment/`. Reuse existing runtime scripts and config examples instead of duplicating logic, and align every section with the current init/fileId implementation.
|
|
||||||
|
|
||||||
**Tech Stack:** Markdown documentation, existing shell scripts, Spring Boot config examples
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Create deployment manual skeleton
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md`
|
|
||||||
|
|
||||||
**Step 1: Draft the document outline**
|
|
||||||
|
|
||||||
Add section headers for:
|
|
||||||
- environment
|
|
||||||
- directory layout
|
|
||||||
- deployment artifacts
|
|
||||||
- config
|
|
||||||
- scripts
|
|
||||||
- file upload/fileId flow
|
|
||||||
- startup operations
|
|
||||||
- precheck
|
|
||||||
- troubleshooting
|
|
||||||
|
|
||||||
**Step 2: Review against current repo assets**
|
|
||||||
|
|
||||||
Verify each section maps to existing files:
|
|
||||||
- `scripts/tms.sh`
|
|
||||||
- `scripts/standard-init/*.sh`
|
|
||||||
- `config/application.yml.example`
|
|
||||||
- init/file upload config
|
|
||||||
|
|
||||||
**Step 3: Write the initial manual content**
|
|
||||||
|
|
||||||
Populate the outline with precise paths and commands using `/home/tms`.
|
|
||||||
|
|
||||||
**Step 4: Link README to the new manual**
|
|
||||||
|
|
||||||
Keep README concise and add a “see full deployment guide” link.
|
|
||||||
|
|
||||||
### Task 2: Document deployment artifacts and directories
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
|
|
||||||
**Step 1: Add directory tree**
|
|
||||||
|
|
||||||
Document:
|
|
||||||
- `/home/tms/tms-framework.jar`
|
|
||||||
- `/home/tms/config/application.yml`
|
|
||||||
- `/home/tms/scripts/tms.sh`
|
|
||||||
- `/home/tms/bin/*.sh`
|
|
||||||
- `/home/tms/uploads`
|
|
||||||
- `/home/tms/logs`
|
|
||||||
- `/home/tms/run`
|
|
||||||
- `/home/tms/tmp`
|
|
||||||
|
|
||||||
**Step 2: Add artifact source mapping**
|
|
||||||
|
|
||||||
State where each deployed file comes from in the repo.
|
|
||||||
|
|
||||||
**Step 3: Add deployment commands**
|
|
||||||
|
|
||||||
Include copy/chmod commands required on CentOS.
|
|
||||||
|
|
||||||
### Task 3: Document config and init dependencies
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example`
|
|
||||||
- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml`
|
|
||||||
|
|
||||||
**Step 1: Document mandatory config items**
|
|
||||||
|
|
||||||
Explain required runtime settings:
|
|
||||||
- security token
|
|
||||||
- upload directory
|
|
||||||
- init executor mode
|
|
||||||
- standard script commands
|
|
||||||
- staging/log directories
|
|
||||||
|
|
||||||
**Step 2: Document standard-init scripts**
|
|
||||||
|
|
||||||
Describe purpose and prerequisites of:
|
|
||||||
- `apply_standard_db.sh`
|
|
||||||
- `start_standard_apps.sh`
|
|
||||||
- `start_standard_nginx.sh`
|
|
||||||
- `check_standard_runtime.sh`
|
|
||||||
|
|
||||||
**Step 3: Document credential handling**
|
|
||||||
|
|
||||||
Clarify which credentials stay in pre-provisioned env vars instead of `application.yml`.
|
|
||||||
|
|
||||||
### Task 4: Document file upload and fileId flow
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
|
|
||||||
**Step 1: Describe upload-first workflow**
|
|
||||||
|
|
||||||
State that init APIs do not accept multipart files and only accept `fileId`.
|
|
||||||
|
|
||||||
**Step 2: Map init fields to uploaded files**
|
|
||||||
|
|
||||||
Document:
|
|
||||||
- `receiverLicenseFileId`
|
|
||||||
- `tlqLicenseFileId`
|
|
||||||
- `cfmqConfigFileId`
|
|
||||||
- `cfgZipFileId`
|
|
||||||
|
|
||||||
**Step 3: Explain storage layout**
|
|
||||||
|
|
||||||
Describe `/home/tms/uploads/<fileId>/<originalFilename>` and how the init executor resolves files.
|
|
||||||
|
|
||||||
### Task 5: Add operations and troubleshooting sections
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md`
|
|
||||||
|
|
||||||
**Step 1: Add start/stop/status commands**
|
|
||||||
|
|
||||||
Document `tms.sh` usage and log locations.
|
|
||||||
|
|
||||||
**Step 2: Add precheck guidance**
|
|
||||||
|
|
||||||
Reference `scripts/cisd_init_precheck.sh` and describe expected pass/fail output.
|
|
||||||
|
|
||||||
**Step 3: Add troubleshooting cases**
|
|
||||||
|
|
||||||
Document diagnosis steps for:
|
|
||||||
- `standardDbApplyCommand is blank`
|
|
||||||
- `cpconfig not found`
|
|
||||||
- uploaded file not found by `fileId`
|
|
||||||
- RabbitMQ command/path errors
|
|
||||||
- WEB/NGINX publish/start issues
|
|
||||||
|
|
||||||
### Task 6: Final review
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Read the final manual top to bottom**
|
|
||||||
|
|
||||||
Check for mismatches against current code/scripts/config.
|
|
||||||
|
|
||||||
**Step 2: Review focused diff**
|
|
||||||
|
|
||||||
Run: `git diff -- README.md docs/deployment/tms-deployment.md`
|
|
||||||
Expected: only deployment documentation changes.
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
# Controller Internal Convention Removal Design
|
|
||||||
|
|
||||||
**Date:** 2026-03-11
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
去掉“非 openapi 接口必须使用 `controller/internal` 包和 `*InternalController` 命名”的项目约定,将内部业务接口控制器统一收敛到中性 `controller` 包和 `*Controller` 类名,同时保持现有 URL、鉴权和 Swagger 暴露行为完全不变。
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
本设计覆盖:
|
|
||||||
- `controller/internal` -> `controller` 的包路径调整
|
|
||||||
- `*InternalController` -> `*Controller` 的类名调整
|
|
||||||
- 测试引用、README、结构说明、命名约定同步更新
|
|
||||||
|
|
||||||
本设计不覆盖:
|
|
||||||
- `/api/**` 与 `/openapi/**` 路径变更
|
|
||||||
- DTO 包结构调整
|
|
||||||
- 鉴权规则变更
|
|
||||||
- `openapi` 控制器命名风格调整
|
|
||||||
- service/repository 结构重构
|
|
||||||
|
|
||||||
## Current State
|
|
||||||
|
|
||||||
当前仓库对内部接口有一套强命名约定:
|
|
||||||
- 内部业务接口通常命名为 `*InternalController`
|
|
||||||
- 其中部分模块控制器位于 `controller/internal`
|
|
||||||
- README 明确规定:`Internal API controllers only in */controller/internal`
|
|
||||||
|
|
||||||
实际代码状态并不统一:
|
|
||||||
- `auth`、`device`、`init`、`system` 使用 `controller` 包,但类名仍为 `*InternalController`
|
|
||||||
- `file` 使用 `controller/internal` 包,类名为 `FileInternalController`
|
|
||||||
- `sign` 模块同时存在 `controller/internal` 和 `controller/openapi`
|
|
||||||
|
|
||||||
这意味着“internal controller”已经被项目文档和部分代码固化,但在包结构上并未完全一致。
|
|
||||||
|
|
||||||
## Design Choice
|
|
||||||
|
|
||||||
采用:`统一改为 controller + *Controller`
|
|
||||||
|
|
||||||
不采用:`只改文档,不改代码`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 用户目标是去掉该设定本身,而不是仅仅弱化描述
|
|
||||||
- 如果只改文档,现有类名和包名仍然持续强化旧约定
|
|
||||||
|
|
||||||
不采用:`只改类名,不改包路径`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- `controller/internal` 目录仍会继续表达旧分层含义
|
|
||||||
- 无法真正完成约定清理
|
|
||||||
|
|
||||||
不采用:`新增一套中性 Controller,保留旧类做代理`
|
|
||||||
|
|
||||||
原因:
|
|
||||||
- 没有兼容性收益
|
|
||||||
- 会引入重复 Bean 或重复请求映射风险
|
|
||||||
|
|
||||||
## Naming Rule After Change
|
|
||||||
|
|
||||||
调整后的规则:
|
|
||||||
- `/api/**` 控制器放在 `modules/*/controller`
|
|
||||||
- `/openapi/**` 控制器继续放在 `modules/*/controller/openapi`
|
|
||||||
- 内部控制器类名使用中性 `*Controller`
|
|
||||||
- 对外接口控制器命名不强制带 `Open` 前缀,但当前已有 `OpenSignController` 可暂时保留
|
|
||||||
|
|
||||||
## Class Rename Plan
|
|
||||||
|
|
||||||
建议重命名如下:
|
|
||||||
- `AuthInternalController` -> `AuthController`
|
|
||||||
- `DeviceInternalController` -> `DeviceController`
|
|
||||||
- `CryptoCardInternalController` -> `CryptoCardController`
|
|
||||||
- `InitInternalController` -> `InitController`
|
|
||||||
- `HealthInternalController` -> `HealthController`
|
|
||||||
- `InternalSignController` -> `SignController`
|
|
||||||
- `FileInternalController` -> `FileController`
|
|
||||||
|
|
||||||
对应包路径调整:
|
|
||||||
- `modules/file/controller/internal` -> `modules/file/controller`
|
|
||||||
- `modules/sign/controller/internal` -> `modules/sign/controller`
|
|
||||||
|
|
||||||
其余当前已在 `controller` 包下的类,仅改类名即可。
|
|
||||||
|
|
||||||
## Compatibility Boundary
|
|
||||||
|
|
||||||
以下内容必须保持不变:
|
|
||||||
- `@RequestMapping` 路径
|
|
||||||
- 所有 `/api/v1/**` 路径
|
|
||||||
- 所有 `/openapi/**` 路径
|
|
||||||
- `WebMvcConfig` 的拦截规则
|
|
||||||
- Swagger/OpenAPI 文档访问路径
|
|
||||||
- 前端、脚本、curl 示例调用路径
|
|
||||||
|
|
||||||
也就是说,这次是纯 Java 命名与项目约定调整,不是 API 行为调整。
|
|
||||||
|
|
||||||
## Security Impact
|
|
||||||
|
|
||||||
鉴权策略不变:
|
|
||||||
- `/api/**` 继续走内部 token 拦截器
|
|
||||||
- `/openapi/**` 继续走 openapi 签名拦截器
|
|
||||||
|
|
||||||
因为拦截器是基于 URL 前缀,而不是控制器类名或包名,所以控制器重命名不会影响运行时鉴权行为。
|
|
||||||
|
|
||||||
## Testing Strategy
|
|
||||||
|
|
||||||
需要验证三类内容:
|
|
||||||
|
|
||||||
1. 编译与导入
|
|
||||||
- 测试类中的 import、`standaloneSetup(...)`、构造器引用都更新完成
|
|
||||||
|
|
||||||
2. 运行时边界不变
|
|
||||||
- 控制器路径不变
|
|
||||||
- 鉴权拦截配置不变
|
|
||||||
|
|
||||||
3. 文档约定更新
|
|
||||||
- README 中模块结构和 API Boundary Rules 不再要求 `controller/internal`
|
|
||||||
- 示例结构改为 `controller + controller/openapi`
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
1. 类名和文件路径同时重命名,容易遗漏测试 import 或文档引用。
|
|
||||||
2. 如果存在基于类名扫描或人工 grep 的脚本,需要同步更新引用。
|
|
||||||
3. `sign` 与 `file` 模块同时涉及包移动,若未同步修改 package 声明会导致编译失败。
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
先做最小一致性改造:
|
|
||||||
- 统一内部控制器类名为 `*Controller`
|
|
||||||
- 去掉 `controller/internal` 包
|
|
||||||
- 更新 README、测试和约定文档
|
|
||||||
|
|
||||||
不在这一轮处理:
|
|
||||||
- `openapi` 控制器风格统一
|
|
||||||
- DTO 包命名统一
|
|
||||||
- 额外的模块结构重构
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
# Controller Internal Convention Removal Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Remove the project-wide `controller/internal` and `*InternalController` convention for non-openapi APIs while keeping all request paths, authentication behavior, and Swagger exposure unchanged.
|
|
||||||
|
|
||||||
**Architecture:** Rename internal API controllers to neutral `*Controller` names and place them under `modules/*/controller`, but leave all `@RequestMapping` values and `WebMvcConfig` interceptor rules untouched. Update tests and README so the repository no longer encodes the old naming convention as a rule.
|
|
||||||
|
|
||||||
**Tech Stack:** Spring Boot MVC, springdoc-openapi, JUnit 5, MockMvc
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Lock down URL and documentation invariants with tests
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java`
|
|
||||||
- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the failing tests**
|
|
||||||
|
|
||||||
Adjust or add tests that assert:
|
|
||||||
- file upload/query endpoints remain `/api/v1/files/**`
|
|
||||||
- Swagger/OpenAPI docs still mention the same URLs
|
|
||||||
- README no longer contains the hard rule `Internal API controllers only in */controller/internal`
|
|
||||||
|
|
||||||
Do not rename production classes yet.
|
|
||||||
|
|
||||||
**Step 2: Run tests to verify they fail**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest,ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: FAIL because tests will still reference old controller names and README still encodes the old convention.
|
|
||||||
|
|
||||||
**Step 3: Keep the tests minimal**
|
|
||||||
|
|
||||||
Limit assertions to:
|
|
||||||
- unchanged routes
|
|
||||||
- removed convention wording
|
|
||||||
- continued `/home/tms/bin` deployment doc assertions already covered in existing tests
|
|
||||||
|
|
||||||
**Step 4: Run tests again to confirm stable RED**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest,ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: FAIL for the intended naming/documentation reasons only.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 2: Rename file and sign internal controllers first
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java`
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/sign/controller/internal/InternalSignController.java`
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java`
|
|
||||||
|
|
||||||
**Step 1: Write the minimal rename**
|
|
||||||
|
|
||||||
Rename and relocate:
|
|
||||||
- `FileInternalController` -> `FileController`
|
|
||||||
- `InternalSignController` -> `SignController`
|
|
||||||
|
|
||||||
Move them into `modules/*/controller`.
|
|
||||||
|
|
||||||
Keep:
|
|
||||||
- package-level Spring scanning working
|
|
||||||
- all request mappings unchanged
|
|
||||||
|
|
||||||
**Step 2: Update tests/imports**
|
|
||||||
|
|
||||||
Update MockMvc standalone setup and imports to use new class names.
|
|
||||||
|
|
||||||
**Step 3: Run focused tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Review for accidental URL changes**
|
|
||||||
|
|
||||||
Check that no `@RequestMapping` strings changed.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 3: Rename the remaining internal controllers
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/auth/controller/AuthInternalController.java`
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/device/controller/DeviceInternalController.java`
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/device/controller/CryptoCardInternalController.java`
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java`
|
|
||||||
- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/system/controller/HealthInternalController.java`
|
|
||||||
- Modify: imports/usages that reference those class names
|
|
||||||
|
|
||||||
**Step 1: Apply the rename set**
|
|
||||||
|
|
||||||
Rename:
|
|
||||||
- `AuthInternalController` -> `AuthController`
|
|
||||||
- `DeviceInternalController` -> `DeviceController`
|
|
||||||
- `CryptoCardInternalController` -> `CryptoCardController`
|
|
||||||
- `InitInternalController` -> `InitController`
|
|
||||||
- `HealthInternalController` -> `HealthController`
|
|
||||||
|
|
||||||
Keep each class in `modules/*/controller`.
|
|
||||||
|
|
||||||
**Step 2: Update all direct references**
|
|
||||||
|
|
||||||
Use `rg` to find and fix:
|
|
||||||
- imports
|
|
||||||
- JavaDoc mentions
|
|
||||||
- comments that name concrete classes
|
|
||||||
|
|
||||||
**Step 3: Run focused compile/test checks**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=InitServiceTest,TmsApplicationTests test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Run compile if needed**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 4: Remove the repository-wide convention from README and docs
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md`
|
|
||||||
- Modify: any design/plan/doc files that are actively used and explicitly enforce `controller/internal`
|
|
||||||
|
|
||||||
**Step 1: Rewrite the structure guidance**
|
|
||||||
|
|
||||||
Update README so it says:
|
|
||||||
- default module layout is `controller + service + repository + entity + dto`
|
|
||||||
- external APIs may additionally use `controller/openapi`
|
|
||||||
|
|
||||||
Remove the hard rule:
|
|
||||||
- `Internal API controllers only in */controller/internal`
|
|
||||||
|
|
||||||
Replace it with a neutral rule:
|
|
||||||
- `/api/**` controllers live under `controller`
|
|
||||||
- `/openapi/**` controllers live under `controller/openapi`
|
|
||||||
|
|
||||||
**Step 2: Update structure tree examples**
|
|
||||||
|
|
||||||
Replace `controller/internal` entries in the README tree with `controller`.
|
|
||||||
|
|
||||||
**Step 3: Run focused documentation regression**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Manual diff review**
|
|
||||||
|
|
||||||
Run: `git diff -- README.md`
|
|
||||||
Expected: naming and structure guidance changes only, no API path changes.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
|
|
||||||
### Task 5: Final verification
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Verify only
|
|
||||||
|
|
||||||
**Step 1: Run controller-related tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=FileInternalControllerTest,InitServiceTest,TmsApplicationTests test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 2: Run documentation regression tests**
|
|
||||||
|
|
||||||
Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 3: Run compile**
|
|
||||||
|
|
||||||
Run: `mvn -q -DskipTests compile`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 4: Review focused diff**
|
|
||||||
|
|
||||||
Run: `git diff -- src/main/java/com/cisd/tms/modules README.md src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java docs/plans/2026-03-11-controller-internal-convention-removal-design.md docs/plans/2026-03-11-controller-internal-convention-removal-plan.md`
|
|
||||||
Expected: only controller renames, import updates, and documentation rule changes.
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
Skip commit in the current dirty workspace per user instruction.
|
|
||||||
-2427
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user