# 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 的存储模型已落地