fix: 素材余量四字段兼容 Asset 领域实体(真实接口恒为 None 修复) (#1550)
CI/CD Pipeline / Check push changed paths (push) Successful in 3m53s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4m32s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m41s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 5m7s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 5m47s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 5m47s
AI Code Review / AI Code Review (pull_request) Failing after 7m21s
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m27s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m11s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m15s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m7s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 54s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m16s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m59s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 10m5s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 10m6s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 10m57s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m10s
CI/CD Pipeline / Integration Tests (push) Successful in 4m49s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m45s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m52s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 5m31s
CI/CD Pipeline / Unit Tests (push) Successful in 18m20s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 13m36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 24s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 414h45m53s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 414h45m53s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 414h45m55s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 414h45m55s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 414h45m55s
CI/CD Pipeline / Production Browser E2E (push) Failing after 414h46m9s
CI/CD Pipeline / Deploy Production (push) Failing after 414h46m10s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 414h46m11s
CI/CD Pipeline / Build Production API Image (push) Failing after 414h46m11s
CI/CD Pipeline / Build Production Web Image (push) Failing after 414h46m11s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Failing after 414h56m29s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 414h56m31s
CI/CD Pipeline / Retag skipped Staging API Image (push) Failing after 414h56m31s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 414h56m33s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 414h56m49s
CI/CD Pipeline / Build Staging Web Image (push) Failing after 414h58m46s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 414h59m3s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 414h59m9s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 414h59m11s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 414h59m15s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 414h59m17s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 414h59m20s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 414h59m22s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 415h0m41s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 415h4m28s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 415h4m30s
CI/CD Pipeline / PR Build API Image (push) Failing after 415h4m31s
CI/CD Pipeline / Frontend Lint (push) Failing after 415h4m32s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 415h4m34s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 415h20m0s
CI/CD Pipeline / Canary Release to Production (push) Failing after 415h20m17s
CI/CD Pipeline / CI Gate (push) Failing after 415h20m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 415h33m14s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 415h33m20s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 415h33m25s
CI/CD Pipeline / PR Build Web Image (push) Failing after 415h38m38s

Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
This commit was merged in pull request #1550.
This commit is contained in:
2026-08-30 08:21:00 +08:00
committed by auto-approve-bot
parent 3acdb8b729
commit 839426a2cc
2 changed files with 52 additions and 8 deletions
+15 -4
View File
@@ -60,12 +60,23 @@ def _now_iso() -> str:
return datetime.now(timezone.utc).isoformat()
def _read_meta(model: AssetModel) -> dict:
"""从 AssetModel 读取 metadata dict(classification_result 列承载的 JSON)."""
if not model.classification_result:
def _read_meta(model) -> dict:
"""读取素材 metadata dict。
兼容两种对象:
- ORM ``AssetModel``:metadata 以 JSON 字符串存在 ``classification_result`` 列;
- 领域实体 ``Asset``(路由层 repository 返回):metadata 直接是 dict 属性
(repository 与 classification_result 互转,见 asset_repository.py)。
"""
# 领域实体:metadata 已是 dict
meta = getattr(model, "metadata", None)
if isinstance(meta, dict):
return meta
raw = getattr(model, "classification_result", None)
if not raw:
return {}
try:
data = json.loads(model.classification_result)
data = json.loads(raw) if isinstance(raw, str) else raw
return data if isinstance(data, dict) else {}
except Exception:
return {}
+37 -4
View File
@@ -36,12 +36,15 @@ VIDEO_DURATION = 60.0
def _make_asset(duration=VIDEO_DURATION, ranges=None, file_type="video", classification_result=None):
"""构造测试用 Asset-like 对象。
"""构造测试用 Asset-like 对象(领域实体形态:metadata 为 dict)。
ranges: list of dicts(used_time_ranges 条目),会自动写入 classification_result JSON。
ranges: list of dicts(used_time_ranges 条目),同时写入 metadata dict
(Asset 实体形态,repository 返回)与 classification_result JSON 字符串
(ORM AssetModel 形态);_read_meta 两种形态都必须能读到。
"""
meta_dict = {"used_time_ranges": ranges} if ranges is not None else {}
if classification_result is None and ranges is not None:
classification_result = json.dumps({"used_time_ranges": ranges})
classification_result = json.dumps(meta_dict)
return SimpleNamespace(
id="asset-test",
project_id="proj-1",
@@ -50,7 +53,6 @@ def _make_asset(duration=VIDEO_DURATION, ranges=None, file_type="video", classif
storage_key="key/test-asset.mp4",
thumbnail_url=None,
mime_type="video/mp4" if file_type == "video" else "audio/mpeg",
metadata={},
file_size=1000,
duration=duration,
width=1080,
@@ -64,10 +66,20 @@ def _make_asset(duration=VIDEO_DURATION, ranges=None, file_type="video", classif
uploaded_by_user_id="user-1",
tag_ids=[],
file_type=file_type,
# ORM 形态
classification_result=classification_result,
# 领域实体形态(真实路由 repository 返回的 Asset)
metadata=meta_dict,
)
def _make_orm_style_asset(duration=VIDEO_DURATION, ranges=None):
"""ORM AssetModel 形态:只有 classification_result JSON 字符串,无 metadata 属性。"""
a = _make_asset(duration=duration, ranges=ranges)
del a.metadata
return a
def _range(start, end, use_count=1):
return {
"start": start,
@@ -227,6 +239,27 @@ class TestComputeAssetAvailability:
"""边缘间隙常量为 0.3s(与 MediaKit 冲突检测同口径)。"""
assert SEGMENT_EDGE_GAP == 0.3
def test_domain_entity_metadata_dict_form(self):
"""领域实体形态(metadata 为 dict,无 classification_result)也能读到区间。
真实路由 repository 返回 Asset 实体,区间记录在 metadata dict 里
(repository 与 ORM classification_result JSON 互转)。
"""
a = _make_asset(duration=30.0, ranges=[_range(0.0, 12.0)])
del a.classification_result # 实体没有该列
info = compute_asset_availability(a)
assert info is not None
assert info["used_duration"] == pytest.approx(12.0, abs=0.01)
assert info["usable"] is True
def test_orm_model_classification_result_form(self):
"""ORM AssetModel 形态(只有 classification_result JSON 字符串)正常。"""
a = _make_orm_style_asset(duration=30.0, ranges=[_range(0.0, 12.0)])
assert not hasattr(a, "metadata")
info = compute_asset_availability(a)
assert info is not None
assert info["used_duration"] == pytest.approx(12.0, abs=0.01)
# ── 路由层辅助:_asset_availability_fields / _to_asset_response ──────────────