refactor(#778): 统一Storage接口,定义StoragePort+SharedStorageService作为唯一入口 #794

Merged
xiaoxia merged 2 commits from refactor/unified-storage-interface into develop 2026-07-24 19:00:13 +08:00
Owner

背景

代码质量专项P1:3份Storage实现分散(SharedStorageService/oss_helpers/OSSStorageService),接口不统一,能力不共享。

改动

  • 新增 packages/ports/storage_port.py → StoragePort 抽象接口(12个核心方法)
  • SharedStorageService 实现 StoragePort,整合两套实现的全部能力:
    • upload_file_smart() 大文件分片上传+超时保护+并发线程(从oss_helpers合并)
    • download_asset() 自动识别URL/存储键,HTTP+SDK双路径下载
    • resolve_asset_path() / resolve_asset_ids_to_paths() 素材路径解析+缓存+安全校验
    • normalize_storage_key() 公开方法
    • connect_timeout=10s 防TCP握手挂死
  • oss_helpers 保留为独立实现(向后兼容,后续逐步迁移到统一入口)
  • API端OSSStorageService保持re-export兼容

验证

  • 全量单测 4383 passed, 8 skipped
  • 2 files changed, +449/-63

Issue

#778

## 背景 代码质量专项P1:3份Storage实现分散(SharedStorageService/oss_helpers/OSSStorageService),接口不统一,能力不共享。 ## 改动 - ✅ 新增 `packages/ports/storage_port.py` → StoragePort 抽象接口(12个核心方法) - ✅ SharedStorageService 实现 StoragePort,整合两套实现的全部能力: - `upload_file_smart()` 大文件分片上传+超时保护+并发线程(从oss_helpers合并) - `download_asset()` 自动识别URL/存储键,HTTP+SDK双路径下载 - `resolve_asset_path()` / `resolve_asset_ids_to_paths()` 素材路径解析+缓存+安全校验 - `normalize_storage_key()` 公开方法 - `connect_timeout=10s` 防TCP握手挂死 - ✅ oss_helpers 保留为独立实现(向后兼容,后续逐步迁移到统一入口) - ✅ API端OSSStorageService保持re-export兼容 ## 验证 - 全量单测 4383 passed, 8 skipped ✅ - 2 files changed, +449/-63 ## Issue #778
xiaoxia force-pushed refactor/unified-storage-interface from d2023a256d to cfc7563520 2026-07-24 00:23:06 +08:00 Compare
xiaoxia added 1 commit 2026-07-24 10:38:01 +08:00
refactor(#778): 统一Storage接口,定义StoragePort+SharedStorageService作为唯一入口
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 23s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m29s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 58s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m18s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 2m20s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m22s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 55s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 27s
AI Code Review / AI Code Review (pull_request) Successful in 3m52s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m59s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
b5bc22834c
- 新增 packages/ports/storage_port.py → StoragePort 抽象接口(12个核心方法)
- SharedStorageService 实现 StoragePort,整合两套实现的全部能力
  - 新增 upload_file_smart():大文件分片上传+超时保护(从oss_helpers合并)
  - 新增 download_asset():自动识别URL/存储键,支持HTTP+SDK双路径
  - 新增 resolve_asset_path() / resolve_asset_ids_to_paths():素材路径解析+缓存
  - 新增 normalize_storage_key() 公开方法
  - connect_timeout=10s 防挂死
- oss_helpers 保留为独立实现(向后兼容,后续逐步迁移)
- 全量单测 4383 passed, 8 skipped
xiaoxia force-pushed refactor/unified-storage-interface from cfc7563520 to b5bc22834c 2026-07-24 10:38:01 +08:00 Compare
xiaoxia added 1 commit 2026-07-24 10:48:04 +08:00
style: black格式化storage.py
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 20s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m2s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 37s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m10s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 39s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m45s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 25s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m25s
AI Code Review / AI Code Review (pull_request) Successful in 3m40s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m25s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 11m21s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m21s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 8m7s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 34m3s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 11s
848705a67d
Collaborator

代码审查结果 - PR #794

⚠️ 问题(3个需要修改)

  1. packages/shared/storage.py 第145行:接口实现与定义不一致,违反里氏替换原则。
    • StoragePort 接口定义 download_file 返回类型为 bool(成功/失败),但 SharedStorageService 实现中返回类型为 None,且失败时抛出异常而非返回 False。这会导致依赖接口进行类型判断的调用方出错。
  2. packages/shared/storage.py 第175行upload_file_smart 存在资源泄漏风险。
    • 当上传线程超时(finished 为 False)时,函数返回 None,但后台线程仍在继续上传文件(因为是 daemon 线程且未做中断处理)。这会导致“僵尸”上传任务持续占用带宽和文件句柄,直到进程结束或上传完成。
  3. packages/shared/storage.py 第133行:假设文件对象可回退(seekable),存在运行时错误风险。
    • 代码无条件调用 file_or_path.seek(0)。如果传入的是不可回退的流(如网络流或管道),会抛出 io.UnsupportedOperation 异常。应增加 seekable 检查或捕获异常。

💡 建议(2个可选)

  1. packages/shared/storage.py 第14行:建议对 requests 库的导入做容错处理。
    • 代码中对 oss2 做了 ImportError 处理,但 requests 是直接导入的。如果环境未安装 requests,会导致模块加载失败。建议保持一致性,添加 try-except 或确保其在依赖列表中。
  2. packages/shared/storage.py 第393行create_direct_upload_post 中的 Content-Type 校验逻辑可优化。
    • content_type.split("/", 1)[0] + "/" 在 Content-Type 为 "image"(无斜杠)时会生成 "image/",这虽然符合 OSS starts-with 逻辑,但语义上略显模糊。建议明确校验格式或补充注释说明此行为。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-24 03:07:06 | 模型:

## 代码审查结果 - PR #794 ### ⚠️ 问题(3个需要修改) 1. **packages/shared/storage.py 第145行**:接口实现与定义不一致,违反里氏替换原则。 - `StoragePort` 接口定义 `download_file` 返回类型为 `bool`(成功/失败),但 `SharedStorageService` 实现中返回类型为 `None`,且失败时抛出异常而非返回 False。这会导致依赖接口进行类型判断的调用方出错。 2. **packages/shared/storage.py 第175行**:`upload_file_smart` 存在资源泄漏风险。 - 当上传线程超时(`finished` 为 False)时,函数返回 None,但后台线程仍在继续上传文件(因为是 daemon 线程且未做中断处理)。这会导致“僵尸”上传任务持续占用带宽和文件句柄,直到进程结束或上传完成。 3. **packages/shared/storage.py 第133行**:假设文件对象可回退(seekable),存在运行时错误风险。 - 代码无条件调用 `file_or_path.seek(0)`。如果传入的是不可回退的流(如网络流或管道),会抛出 `io.UnsupportedOperation` 异常。应增加 `seekable` 检查或捕获异常。 ### 💡 建议(2个可选) 1. **packages/shared/storage.py 第14行**:建议对 `requests` 库的导入做容错处理。 - 代码中对 `oss2` 做了 `ImportError` 处理,但 `requests` 是直接导入的。如果环境未安装 `requests`,会导致模块加载失败。建议保持一致性,添加 try-except 或确保其在依赖列表中。 2. **packages/shared/storage.py 第393行**:`create_direct_upload_post` 中的 Content-Type 校验逻辑可优化。 - `content_type.split("/", 1)[0] + "/"` 在 Content-Type 为 "image"(无斜杠)时会生成 "image/",这虽然符合 OSS starts-with 逻辑,但语义上略显模糊。建议明确校验格式或补充注释说明此行为。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-24 03:07:06 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 3ae15eb4fc into develop 2026-07-24 19:00:13 +08:00
xiaoxia deleted branch refactor/unified-storage-interface 2026-07-24 19:00:13 +08:00

🗑️ 预览环境已清理

PR #794 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #794 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.