458 lines
11 KiB
Markdown
458 lines
11 KiB
Markdown
# FTP 同步工具详细设计
|
|
|
|
## 1. 文档说明
|
|
|
|
本文档是对总体方案的继续细化,重点补充以下内容:
|
|
|
|
- `application.properties` 配置方案
|
|
- H2 表结构与初始化方式
|
|
- Spring Boot 2.7.18 工程骨架
|
|
- 核心类职责划分
|
|
- 启动方式与后续待实现事项
|
|
|
|
## 2. 配置文件策略
|
|
|
|
本项目采用 `properties` 配置文件,不使用 `yml`。
|
|
|
|
推荐目录如下:
|
|
|
|
```text
|
|
src/main/resources/
|
|
|- application.properties
|
|
|- application-dev-agent.properties
|
|
|- application-prod-agent.properties
|
|
|- schema.sql
|
|
```
|
|
|
|
配置分工如下:
|
|
|
|
- `application.properties`
|
|
- 放公共配置
|
|
- 包括数据源、H2、通用路径、FTP 默认项、Git 默认项、生产接口默认项
|
|
- `application-dev-agent.properties`
|
|
- 放开发环境代理专属配置
|
|
- 包括开发侧定时任务表达式、开发侧 FTP 账号、Git 仓库分支
|
|
- `application-prod-agent.properties`
|
|
- 放生产环境代理专属配置
|
|
- 包括生产侧定时任务表达式、生产侧 FTP 账号、生产接口地址与认证
|
|
|
|
## 3. 当前配置项设计
|
|
|
|
### 3.1 公共配置
|
|
|
|
已落地文件:
|
|
|
|
- [application.properties](e:/AIcoding/FtpTool/src/main/resources/application.properties)
|
|
|
|
核心配置分组如下:
|
|
|
|
### `spring.*`
|
|
|
|
- `spring.application.name`
|
|
- `spring.datasource.*`
|
|
- `spring.jpa.*`
|
|
- `spring.sql.init.*`
|
|
- `spring.h2.console.*`
|
|
|
|
用途:
|
|
|
|
- 启动 Spring Boot
|
|
- 使用 H2 文件数据库
|
|
- 通过 `schema.sql` 初始化表结构
|
|
|
|
### `sync.*`
|
|
|
|
- `sync.node-id`
|
|
- `sync.role`
|
|
- `sync.work-dir`
|
|
- `sync.package-temp-dir`
|
|
- `sync.dev-to-prod-staging-dir`
|
|
- `sync.prod-to-dev-staging-dir`
|
|
- `sync.max-retry-count`
|
|
- `sync.ack-scan-batch-size`
|
|
|
|
用途:
|
|
|
|
- 标识当前节点身份
|
|
- 控制工作目录和临时目录
|
|
- 控制同步重试与 ack 扫描参数
|
|
|
|
### `ftp.*`
|
|
|
|
- `ftp.host`
|
|
- `ftp.port`
|
|
- `ftp.username`
|
|
- `ftp.password`
|
|
- `ftp.passive-mode`
|
|
- `ftp.base-dir`
|
|
- `ftp.connect-timeout-ms`
|
|
- `ftp.data-timeout-ms`
|
|
- `ftp.buffer-size`
|
|
|
|
用途:
|
|
|
|
- 定义 FTP 连接参数
|
|
- 定义远端根目录和超时策略
|
|
|
|
### `git.repo.*`
|
|
|
|
- `git.repo.local-path`
|
|
- `git.repo.remote-uri`
|
|
- `git.repo.username`
|
|
- `git.repo.password`
|
|
- `git.repo.scan-branch`
|
|
- `git.repo.snapshot-branch`
|
|
- `git.repo.commit-author-name`
|
|
- `git.repo.commit-author-email`
|
|
- `git.repo.commit-message-prefix`
|
|
- `git.repo.pull-rebase`
|
|
|
|
用途:
|
|
|
|
- 定义开发侧 Git 拉取与提交行为
|
|
- 指定开发主分支和生产镜像分支
|
|
|
|
### `prod.api.*`
|
|
|
|
- `prod.api.base-url`
|
|
- `prod.api.push-path`
|
|
- `prod.api.pull-path`
|
|
- `prod.api.token`
|
|
- `prod.api.connect-timeout-ms`
|
|
- `prod.api.read-timeout-ms`
|
|
|
|
用途:
|
|
|
|
- 定义生产侧 `push/pull` 接口的连接方式
|
|
|
|
## 4. Profile 设计
|
|
|
|
### 4.1 开发代理 Profile
|
|
|
|
已落地文件:
|
|
|
|
- [application-dev-agent.properties](e:/AIcoding/FtpTool/src/main/resources/application-dev-agent.properties)
|
|
|
|
主要内容:
|
|
|
|
- `spring.config.activate.on-profile=dev-agent`
|
|
- 开发侧端口
|
|
- 开发侧三类任务 cron
|
|
- 开发侧 FTP 账号示例
|
|
- Git 分支覆盖项
|
|
|
|
当前定时任务:
|
|
|
|
- `sync.jobs.dev-git-scan.cron`
|
|
- `sync.jobs.dev-consume-prod-package.cron`
|
|
- `sync.jobs.dev-ack-scan.cron`
|
|
|
|
### 4.2 生产代理 Profile
|
|
|
|
已落地文件:
|
|
|
|
- [application-prod-agent.properties](e:/AIcoding/FtpTool/src/main/resources/application-prod-agent.properties)
|
|
|
|
主要内容:
|
|
|
|
- `spring.config.activate.on-profile=prod-agent`
|
|
- 生产侧端口
|
|
- 生产侧三类任务 cron
|
|
- 生产侧 FTP 账号示例
|
|
- 生产接口地址和 token 示例
|
|
|
|
当前定时任务:
|
|
|
|
- `sync.jobs.prod-consume-dev-package.cron`
|
|
- `sync.jobs.prod-pull-config.cron`
|
|
- `sync.jobs.prod-ack-scan.cron`
|
|
|
|
## 5. H2 设计
|
|
|
|
已落地文件:
|
|
|
|
- [schema.sql](e:/AIcoding/FtpTool/src/main/resources/schema.sql)
|
|
|
|
### 5.1 初始化方式
|
|
|
|
通过以下配置自动初始化:
|
|
|
|
```properties
|
|
spring.sql.init.mode=always
|
|
spring.sql.init.schema-locations=classpath:schema.sql
|
|
spring.jpa.hibernate.ddl-auto=none
|
|
```
|
|
|
|
说明:
|
|
|
|
- 表结构由手工 SQL 控制
|
|
- 不依赖 Hibernate 自动建表
|
|
- 更适合后续环境迁移和版本管理
|
|
|
|
### 5.2 已定义表
|
|
|
|
#### `sync_checkpoint`
|
|
|
|
用途:
|
|
|
|
- 保存每个同步方向最后一次成功版本
|
|
|
|
关键字段:
|
|
|
|
- `direction`
|
|
- `last_success_version`
|
|
- `last_success_hash`
|
|
- `updated_at`
|
|
|
|
#### `sync_task`
|
|
|
|
用途:
|
|
|
|
- 保存每次同步任务实例
|
|
|
|
关键字段:
|
|
|
|
- `trace_id`
|
|
- `direction`
|
|
- `source_version`
|
|
- `content_hash`
|
|
- `package_name`
|
|
- `status`
|
|
- `retry_count`
|
|
- `error_msg`
|
|
|
|
关键约束:
|
|
|
|
- `trace_id` 唯一
|
|
- `direction + source_version + content_hash` 唯一
|
|
|
|
这组唯一键就是当前骨架里默认采用的幂等键。
|
|
|
|
#### `sync_ack`
|
|
|
|
用途:
|
|
|
|
- 保存跨端 ack 回执
|
|
|
|
关键字段:
|
|
|
|
- `trace_id`
|
|
- `ack_side`
|
|
- `ack_status`
|
|
- `ack_time`
|
|
- `remark`
|
|
|
|
## 6. 工程骨架
|
|
|
|
当前已经在仓库中生成了一套最小 Spring Boot 骨架。
|
|
|
|
### 6.1 构建文件
|
|
|
|
- [pom.xml](e:/AIcoding/FtpTool/pom.xml)
|
|
|
|
已引入的核心依赖:
|
|
|
|
- `spring-boot-starter`
|
|
- `spring-boot-starter-web`
|
|
- `spring-boot-starter-data-jpa`
|
|
- `spring-boot-starter-actuator`
|
|
- `spring-retry`
|
|
- `commons-net`
|
|
- `org.eclipse.jgit`
|
|
- `h2`
|
|
|
|
### 6.2 启动类
|
|
|
|
- [FtpSyncToolApplication.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/FtpSyncToolApplication.java)
|
|
|
|
作用:
|
|
|
|
- 启用 Spring Boot
|
|
- 启用定时任务
|
|
- 启用重试机制
|
|
- 注册配置属性类
|
|
|
|
### 6.3 配置属性类
|
|
|
|
- [SyncProperties.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/config/SyncProperties.java)
|
|
- [FtpProperties.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/config/FtpProperties.java)
|
|
- [GitRepoProperties.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/config/GitRepoProperties.java)
|
|
- [ProdApiProperties.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/config/ProdApiProperties.java)
|
|
|
|
作用:
|
|
|
|
- 将 `properties` 配置映射为强类型对象
|
|
- 避免业务代码直接散落读取字符串 key
|
|
|
|
### 6.4 基础配置
|
|
|
|
- [AppConfig.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/config/AppConfig.java)
|
|
|
|
当前提供:
|
|
|
|
- `RestTemplate` Bean
|
|
- 读取生产接口超时参数
|
|
|
|
## 7. 领域模型与仓储
|
|
|
|
### 7.1 枚举
|
|
|
|
- [SyncDirection.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/model/SyncDirection.java)
|
|
- [SyncRole.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/model/SyncRole.java)
|
|
- [SyncStatus.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/model/SyncStatus.java)
|
|
|
|
用途:
|
|
|
|
- 统一同步方向、角色和状态定义
|
|
|
|
### 7.2 实体
|
|
|
|
- [SyncTask.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/entity/SyncTask.java)
|
|
- [SyncCheckpoint.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/entity/SyncCheckpoint.java)
|
|
- [SyncAck.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/entity/SyncAck.java)
|
|
|
|
用途:
|
|
|
|
- 对应 H2 三张核心业务表
|
|
- 内置了基础时间戳维护逻辑
|
|
|
|
### 7.3 Repository
|
|
|
|
- [SyncTaskRepository.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/repository/SyncTaskRepository.java)
|
|
- [SyncCheckpointRepository.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/repository/SyncCheckpointRepository.java)
|
|
- [SyncAckRepository.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/repository/SyncAckRepository.java)
|
|
|
|
用途:
|
|
|
|
- 提供基础持久化能力
|
|
- 已包含按幂等键和 `traceId` 查询的方法
|
|
|
|
## 8. 当前服务层设计
|
|
|
|
### 8.1 已实现基础服务
|
|
|
|
- [SyncTaskService.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/service/SyncTaskService.java)
|
|
- [CheckpointService.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/service/CheckpointService.java)
|
|
- [AckService.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/service/AckService.java)
|
|
|
|
当前能力:
|
|
|
|
- 创建或加载幂等任务
|
|
- 更新任务状态
|
|
- 增加重试次数
|
|
- 更新检查点
|
|
- 记录 ack 回执
|
|
|
|
### 8.2 当前未实现的业务服务
|
|
|
|
当前骨架还没有把以下真实能力写完:
|
|
|
|
- FTP 上传、下载、列目录、重命名
|
|
- Git clone / pull / checkout / commit / push
|
|
- zip 打包与解包
|
|
- manifest 生成与校验
|
|
- 生产 `push` / `pull` 接口调用
|
|
|
|
这些是下一步真正要补的业务实现层。
|
|
|
|
## 9. 当前调度层设计
|
|
|
|
### 9.1 开发侧调度
|
|
|
|
- [DevSyncCoordinator.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/orchestrator/DevSyncCoordinator.java)
|
|
- [DevGitScanJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/DevGitScanJob.java)
|
|
- [DevConsumeProdPackageJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/DevConsumeProdPackageJob.java)
|
|
- [DevAckScanJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/DevAckScanJob.java)
|
|
|
|
当前状态:
|
|
|
|
- 已按 `dev-agent` profile 进行隔离
|
|
- 已绑定 cron 表达式
|
|
- 当前仅输出清晰日志和待办动作
|
|
|
|
### 9.2 生产侧调度
|
|
|
|
- [ProdSyncCoordinator.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/orchestrator/ProdSyncCoordinator.java)
|
|
- [ProdConsumeDevPackageJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/ProdConsumeDevPackageJob.java)
|
|
- [ProdPullConfigJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/ProdPullConfigJob.java)
|
|
- [ProdAckScanJob.java](e:/AIcoding/FtpTool/src/main/java/com/ftptool/sync/job/ProdAckScanJob.java)
|
|
|
|
当前状态:
|
|
|
|
- 已按 `prod-agent` profile 进行隔离
|
|
- 已绑定 cron 表达式
|
|
- 当前仅输出清晰日志和待办动作
|
|
|
|
## 10. 当前目录结构
|
|
|
|
```text
|
|
FtpTool
|
|
|- docs
|
|
|- pom.xml
|
|
|- src
|
|
|- main
|
|
|- java/com/ftptool/sync
|
|
| |- config
|
|
| |- entity
|
|
| |- job
|
|
| |- model
|
|
| |- orchestrator
|
|
| |- repository
|
|
| |- service
|
|
|- resources
|
|
|- application.properties
|
|
|- application-dev-agent.properties
|
|
|- application-prod-agent.properties
|
|
|- schema.sql
|
|
```
|
|
|
|
## 11. 启动方式
|
|
|
|
### 11.1 启动开发代理
|
|
|
|
```bash
|
|
mvn spring-boot:run -Dspring-boot.run.profiles=dev-agent
|
|
```
|
|
|
|
### 11.2 启动生产代理
|
|
|
|
```bash
|
|
mvn spring-boot:run -Dspring-boot.run.profiles=prod-agent
|
|
```
|
|
|
|
也可以打包后通过 JVM 参数指定:
|
|
|
|
```bash
|
|
java -jar ftp-sync-tool.jar --spring.profiles.active=dev-agent
|
|
java -jar ftp-sync-tool.jar --spring.profiles.active=prod-agent
|
|
```
|
|
|
|
## 12. 下一步建议实现顺序
|
|
|
|
建议按以下顺序继续落代码:
|
|
|
|
1. 先实现 `FtpClientService`
|
|
2. 再实现 `GitClientService`
|
|
3. 再实现 `PackageService`
|
|
4. 再实现 `ProdConfigApiService`
|
|
5. 最后把 `Coordinator` 中的 TODO 串起来
|
|
|
|
## 13. 当前边界
|
|
|
|
当前骨架是“可扩展的项目起点”,不是完整业务实现,现阶段还缺:
|
|
|
|
- 真正的 FTP 交互
|
|
- 真正的 Git 操作
|
|
- 真正的生产接口调用
|
|
- 包文件读写与校验
|
|
- ack 文件协议
|
|
- 失败重试细节和告警
|
|
|
|
但好处是结构已经固定住了:
|
|
|
|
- 配置口径统一为 `properties`
|
|
- profile 隔离清晰
|
|
- H2 状态表已定义
|
|
- 调度入口已分开
|
|
- 任务、检查点、ack 的存储模型已落地
|