329 lines
11 KiB
Markdown
329 lines
11 KiB
Markdown
# 后端重构方案草案
|
||
|
||
## 一、需要重构的模块
|
||
|
||
1. 在线快传模块
|
||
- 相关代码:`transfer/TransferService`、`transfer/TransferSessionStore`、`transfer/TransferSession`
|
||
|
||
2. 离线快传模块
|
||
- 相关代码:`transfer/TransferService`、`OfflineTransferSessionRepository`、存储额度相关 admin 指标逻辑
|
||
|
||
3. 异步任务模块
|
||
- 相关代码:`files/tasks/BackgroundTaskService`、`BackgroundTaskWorker`、`BackgroundTaskRepository`、`BackgroundTask`
|
||
|
||
4. Broker 消息模块
|
||
- 相关代码:`common/broker/*`、`MediaMetadataTaskBrokerPublisher`、`MediaMetadataTaskBrokerConsumer`
|
||
|
||
5. 文件事件模块
|
||
- 相关代码:`files/events/FileEventService`、`RedisFileEventPubSubPublisher`、`RedisFileEventPubSubListener`
|
||
|
||
6. 上传会话模块
|
||
- 相关代码:`files/upload/UploadSessionService`、`UploadSessionRuntimeStateService`、`RedisUploadSessionRuntimeStateService`
|
||
|
||
7. 认证会话模块
|
||
- 相关代码:`auth/AuthService`、`RefreshTokenService`、`AuthTokenInvalidationService`、`config/JwtAuthenticationFilter`
|
||
|
||
8. Admin 设置模块
|
||
- 相关代码:`admin/AdminService`、settings/filesystem 相关 DTO 和 controller
|
||
|
||
## 二、每个模块现在的问题
|
||
|
||
### 1. 在线快传模块
|
||
- 业务目标看起来是“支持 Redis + 多实例 + 分布式锁”。
|
||
- 但当前锁只包读取,不包“读取后修改再保存”整个事务。
|
||
- Redis 模式下是整对象覆盖写,存在并发覆盖和信令丢失问题。
|
||
- “仅允许一个接收方加入”是业务规则,但现在不能稳定保证。
|
||
|
||
### 2. 离线快传模块
|
||
- 会话、文件上传、ready 状态、存储额度检查都耦合在 `TransferService`。
|
||
- 存储额度检查不是原子行为,并发上传可能突破上限。
|
||
- 上传状态推进和额度校验缺少统一状态机。
|
||
|
||
### 3. 异步任务模块
|
||
- 任务创建、claim、lease、heartbeat、retry、manual retry、状态 JSON 解析都混在一个 service。
|
||
- `correlationId` 被当作幂等键使用,但没有数据库级保证。
|
||
- attempt/retry 语义虽然有实现,但规则没有被明确定义和隔离。
|
||
- `public_state_json/private_state_json` 既是业务状态,又承担运行态和展示态,职责混杂。
|
||
|
||
### 4. Broker 消息模块
|
||
- 当前消费语义是“先 pop 再处理”,天然是 at-most-once。
|
||
- 但业务又想靠 `correlationId` 做去重,更像 at-least-once。
|
||
- 消息可靠性、重试、死信、幂等边界都没有单独建模。
|
||
- broker 只是技术实现,但现在承担了业务可靠性语义。
|
||
|
||
### 5. 文件事件模块
|
||
- 本地 SSE 推送、事件持久化、跨实例广播在一个 service 中耦合。
|
||
- listener 对坏消息直接抛异常,容错策略不清晰。
|
||
- 本地订阅过滤规则、跨实例复制规则、事件 payload 规则没有独立边界。
|
||
|
||
### 6. 上传会话模块
|
||
- DB 状态和 Redis runtime 状态并存,但权威关系没有被结构化表达。
|
||
- Redis runtime 读写失败基本是静默处理,观测和告警语义不明确。
|
||
- 上传模式判断、会话状态推进、远端对象清理、运行态刷新都在一个 service 里。
|
||
|
||
### 7. 认证会话模块
|
||
- access token 吊销、refresh token 轮换、active session 切换、封禁/改密后的清理都存在,但没有统一策略层。
|
||
- “立即失效”的定义不够严格,尤其是时间边界处理。
|
||
- 桌面端/移动端的单端活跃规则散落在多个方法中。
|
||
|
||
### 8. Admin 设置模块
|
||
- 可写设置、运行态快照、环境配置读取混在一个聚合响应里。
|
||
- `writeSupported` 只能提示能力,不能从结构上表达“配置源”和“运行态”区别。
|
||
- 业务上已经有“可持久化设置”和“只读快照”两类概念,但代码层还没完全分开。
|
||
|
||
## 三、应该如何拆分职责
|
||
|
||
### 1. 在线快传模块
|
||
建议拆成:
|
||
- `OnlineTransferSessionService`
|
||
- 负责业务规则:join、postSignal、poll、过期判断
|
||
- `OnlineTransferSessionRepository`
|
||
- 负责会话持久化/加载
|
||
- `OnlineTransferSessionLockManager`
|
||
- 负责会话级原子执行
|
||
- `OnlineTransferSessionAggregate`
|
||
- 负责接收方唯一、信令队列、cursor 等领域行为
|
||
|
||
目标:
|
||
- 所有读改写保存通过一个原子入口完成
|
||
- service 不直接操作 Redis 细节
|
||
|
||
### 2. 离线快传模块
|
||
建议拆成:
|
||
- `OfflineTransferSessionService`
|
||
- `OfflineTransferStorageQuotaService`
|
||
- `OfflineTransferFileStorageService`
|
||
|
||
目标:
|
||
- 会话状态推进和额度规则分离
|
||
- 上传文件、ready 判定、容量扣减有清晰边界
|
||
|
||
### 3. 异步任务模块
|
||
建议拆成:
|
||
- `BackgroundTaskCommandService`
|
||
- 创建、取消、人工重试
|
||
- `BackgroundTaskExecutionService`
|
||
- claim、heartbeat、complete、fail
|
||
- `BackgroundTaskRetryPolicy`
|
||
- retryable、attempt、delay 计算
|
||
- `BackgroundTaskStateCodec`
|
||
- JSON <-> typed state
|
||
- `BackgroundTaskIdempotencyService`
|
||
- correlationId 规则
|
||
|
||
目标:
|
||
- “任务业务规则”和“任务运行机制”分离
|
||
- state JSON 不再到处手写 merge/remove
|
||
|
||
### 4. Broker 消息模块
|
||
建议拆成:
|
||
- `BrokerMessagePublisher`
|
||
- `BrokerMessageConsumer`
|
||
- `BrokerDeliveryPolicy`
|
||
- `BrokerMessageHandler`
|
||
|
||
目标:
|
||
- 明确消息语义是 at-least-once
|
||
- 可靠性和业务处理解耦
|
||
- 去重不靠消费者临时判断,而靠任务幂等层
|
||
|
||
### 5. 文件事件模块
|
||
建议拆成:
|
||
- `FileEventRecorder`
|
||
- 落库
|
||
- `FileEventDispatcher`
|
||
- 本地 SSE 分发
|
||
- `FileEventReplicationPublisher`
|
||
- 跨实例发布
|
||
- `FileEventReplicationConsumer`
|
||
- 跨实例消费
|
||
- `FileEventPayloadCodec`
|
||
- payload 结构规则
|
||
|
||
目标:
|
||
- 本地分发和跨实例同步分离
|
||
- 坏消息只影响当前消息,不影响整体监听
|
||
|
||
### 6. 上传会话模块
|
||
建议拆成:
|
||
- `UploadSessionLifecycleService`
|
||
- create/cancel/complete/prune
|
||
- `UploadSessionContentService`
|
||
- prepare/upload/part-record
|
||
- `UploadSessionRuntimeViewService`
|
||
- 运行态读取
|
||
- `UploadSessionRuntimeStateStore`
|
||
- Redis/no-op 存储实现
|
||
- `UploadPolicyResolver`
|
||
- 上传模式、大小限制、策略能力决策
|
||
|
||
目标:
|
||
- DB 生命周期和 Redis 观测态分离
|
||
- runtime state 明确为辅助层
|
||
|
||
### 7. 认证会话模块
|
||
建议拆成:
|
||
- `AuthSessionPolicy`
|
||
- 单端活跃、吊销、生效边界
|
||
- `AccessTokenRevocationService`
|
||
- `RefreshTokenRotationService`
|
||
- `UserSessionRotationService`
|
||
|
||
目标:
|
||
- 改密/封禁/登录/刷新都走同一套会话规则
|
||
- 避免规则散落在 `AuthService` 和 admin 逻辑里
|
||
|
||
### 8. Admin 设置模块
|
||
建议拆成:
|
||
- `AdminConfigSnapshotService`
|
||
- 只读运行态
|
||
- `AdminMutableSettingsService`
|
||
- 可写设置
|
||
- `AdminSettingsFacade`
|
||
- 对外聚合
|
||
|
||
目标:
|
||
- 区分“系统当前状态”和“可持久化业务设置”
|
||
- 减少 admin service 持续膨胀
|
||
|
||
## 四、哪些逻辑应抽到公共规则层
|
||
|
||
这些不该继续散在各 service 里:
|
||
|
||
### 1. 幂等规则层
|
||
- `correlationId` 生成规则
|
||
- 同一业务动作是否允许重复创建任务
|
||
- 幂等冲突时返回什么结果
|
||
|
||
### 2. 状态机规则层
|
||
- 在线快传会话状态推进
|
||
- 离线快传 ready 条件
|
||
- 上传会话状态推进
|
||
- 后台任务状态推进
|
||
|
||
### 3. 并发规则层
|
||
- 会话级锁
|
||
- 额度检查的原子更新
|
||
- 任务 claim/lease 规则
|
||
|
||
### 4. 重试规则层
|
||
- 哪些错误可重试
|
||
- attemptCount 如何累积
|
||
- 自动重试和人工重试的区别
|
||
- backoff 计算规则
|
||
|
||
### 5. 认证会话规则层
|
||
- 单端活跃规则
|
||
- 改密/封禁/重置密码后的清理规则
|
||
- access token / refresh token 失效边界
|
||
|
||
### 6. 事件与消息规则层
|
||
- file event payload 结构
|
||
- listener 遇到坏消息如何处理
|
||
- broker 消息投递语义
|
||
|
||
### 7. 配置语义规则层
|
||
- “运行态快照”
|
||
- “持久化设置”
|
||
- “环境配置只读项”
|
||
|
||
## 五、推荐重构顺序
|
||
|
||
### 第一阶段:先统一规则,再动结构
|
||
1. 先定四个核心语义
|
||
- 在线快传并发语义
|
||
- 异步任务幂等语义
|
||
- broker 投递语义
|
||
- 认证会话失效语义
|
||
|
||
2. 把这些规则抽成独立策略/规则类
|
||
- 先不大改 controller 和 repository
|
||
|
||
### 第二阶段:先改最危险的一致性问题
|
||
1. 在线快传
|
||
- 把读改写保存收敛到单个原子入口
|
||
2. 异步任务幂等
|
||
- 让 `correlationId` 成为真正约束
|
||
3. broker 消费可靠性
|
||
- 不再“先丢消息再处理”
|
||
|
||
### 第三阶段:收敛状态机和运行机制
|
||
1. 后台任务状态机拆分
|
||
2. 上传会话 lifecycle/runtime 拆分
|
||
3. 文件事件 recorder/dispatcher/replication 拆分
|
||
|
||
### 第四阶段:清理配置和管理侧语义
|
||
1. admin settings 拆成 snapshot + mutable settings
|
||
2. auth session 规则统一落到策略层
|
||
3. 去掉 service 中分散的规则分支
|
||
|
||
## 六、建议优先落地的重构任务列表
|
||
|
||
1. 先定义并固定“统一业务规则”接口
|
||
- 不改功能,只固化规则边界
|
||
|
||
2. 重构在线快传
|
||
- 先解决原子性问题
|
||
|
||
3. 重构后台任务幂等和 broker
|
||
- 先解决重复任务和消息丢失问题
|
||
|
||
4. 重构后台任务状态机
|
||
- 把 retry/lease/attempt 语义统一
|
||
|
||
5. 重构文件事件模块
|
||
- 提高跨实例容错
|
||
|
||
6. 重构上传会话模块
|
||
- 明确 DB 状态与 Redis runtime 的关系
|
||
|
||
7. 最后整理 auth/admin
|
||
- 收口规则,减少横向重复逻辑
|
||
|
||
## 必须先达成一致的核心规则
|
||
|
||
1. 在线快传必须是“原子读改写”,不能接受覆盖写丢信令
|
||
2. 自动媒体任务必须以“任务幂等”保证最终唯一,不能靠先查再插
|
||
3. broker 语义统一为“至少投递一次 + 消费端幂等”
|
||
4. 后台任务 `attemptCount`、自动重试、人工重试必须统一定义
|
||
5. 上传会话中 DB 状态是权威状态,Redis 只做辅助观测
|
||
6. 文件事件坏消息必须隔离处理,不能拖垮整个 listener
|
||
7. 认证相关的“立即失效”必须有明确且统一的规则
|
||
8. admin 设置必须区分“运行态快照”和“可写业务设置”
|
||
|
||
## 2026-04-11 Execution Status
|
||
|
||
Completed in the first implementation batch:
|
||
|
||
1. Extracted task rule components from `BackgroundTaskService`
|
||
- `BackgroundTaskRetryPolicy`
|
||
- `BackgroundTaskStateManager`
|
||
- `BackgroundTaskStateKeys`
|
||
|
||
2. Split file-event orchestration from local dispatch
|
||
- `FileEventService` now coordinates persistence and after-commit publishing
|
||
- `FileEventDispatcher` owns local SSE subscription and delivery
|
||
- `FileEventPayloadCodec` owns payload shaping
|
||
- malformed Redis pub/sub payloads are isolated and dropped by the listener
|
||
|
||
3. Split upload rules from upload-session orchestration
|
||
- `UploadPolicyResolver` owns upload-mode and size/chunk rules
|
||
- `UploadSessionStateMachine` owns lifecycle transitions
|
||
- `UploadSessionService` now coordinates repository + runtime-state updates around those rules
|
||
|
||
4. Extracted auth session rotation rules
|
||
- `AuthSessionPolicy` now owns per-client session rotation semantics used by `AuthService`
|
||
|
||
Verification:
|
||
|
||
- `cd backend && mvn "-Dtest=BackgroundTaskRetryPolicyTest,UploadSessionStateMachineTest,AuthSessionPolicyTest,FileEventServiceTest,RedisFileEventPubSubListenerTest,BackgroundTaskServiceTest,UploadSessionServiceTest,AuthServiceTest" test`
|
||
- `cd backend && mvn test`
|
||
|
||
Current remaining high-value work from this plan:
|
||
|
||
- deeper background-task command/execution separation
|
||
- offline-transfer quota atomicity split
|
||
- broader file-event replication boundary cleanup
|
||
- admin snapshot vs mutable-settings facade split
|
||
- further auth/admin rule consolidation
|