chore(format): fix black/isort after rebase to develop
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 34s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m50s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m14s

This commit is contained in:
CI Bot
2026-07-13 00:30:24 +08:00
parent a317f02d3f
commit e02a7475bc
6 changed files with 13 additions and 39 deletions
+1 -3
View File
@@ -48,9 +48,7 @@ class FeatureFlagUpdateRequest(BaseModel):
enabled: bool = Field(..., description="是否启用")
percentage: int = Field(0, ge=0, le=100, description="灰度百分比 (0-100)")
whitelist: list[str] = Field(
default_factory=list, description="白名单列表(如 user_id"
)
whitelist: list[str] = Field(default_factory=list, description="白名单列表(如 user_id")
class FeatureFlagResponse(BaseModel):
+1 -1
View File
@@ -6,8 +6,8 @@
from . import dedup_helpers, ffmpeg_utils, oss_helpers
from .processor import VideoProcessor, VideoResult
from .render_adapter import RenderAdapter, RenderAdapterResult
from .unified_render_service import RenderResult, UnifiedRenderService
from .render_engine_resolver import RenderEngineResolver, get_render_engine_resolver
from .unified_render_service import RenderResult, UnifiedRenderService
__all__ = [
"VideoProcessor",
@@ -61,9 +61,7 @@ class RenderEngineResolver:
refresh_interval: Redis flag 配置刷新间隔(秒)
store: 直接传入 store 实例(测试用,优先级高于 redis_url)
"""
self._default_engine = (
default_engine.lower() if default_engine else ENGINE_LEGACY
)
self._default_engine = default_engine.lower() if default_engine else ENGINE_LEGACY
if self._default_engine not in VALID_ENGINES:
logger.warning(
"Invalid default engine '%s', fallback to '%s'",
@@ -188,9 +186,7 @@ def get_render_engine_resolver() -> RenderEngineResolver:
from worker_app.core.config import get_settings
settings = get_settings()
redis_url = getattr(settings, "redis_url", None) or getattr(
settings, "broker_url", None
)
redis_url = getattr(settings, "redis_url", None) or getattr(settings, "broker_url", None)
default = getattr(settings, "render_engine", ENGINE_LEGACY)
_resolver = RenderEngineResolver(
default_engine=default,
@@ -109,9 +109,7 @@ def _compose_with_legacy_engine(task, job_service, job, plan_id: str, db) -> dic
# 构建合成命令
job_service.update_progress(job_id, progress=30.0, current_stage="构建 FFmpeg 命令")
_output_dir = os.environ.get(
"VIDEO_OUTPUT_DIR", os.path.join(tempfile.gettempdir(), "video_output")
)
_output_dir = os.environ.get("VIDEO_OUTPUT_DIR", os.path.join(tempfile.gettempdir(), "video_output"))
output_path = os.path.join(_output_dir, f"{job_id}.mp4")
compose_cmd = compose_svc.build_compose_command(plan_id, output_path)
@@ -161,9 +159,7 @@ def _compose_with_unified_engine(task, job_service, job, plan_id: str, db) -> di
job_id = job.id
# 标记为 running
job_service.update_progress(
job_id, progress=10.0, current_stage="初始化统一渲染引擎"
)
job_service.update_progress(job_id, progress=10.0, current_stage="初始化统一渲染引擎")
from video_processing.render_adapter import RenderAdapter
@@ -225,9 +221,7 @@ def _compose_with_unified_engine(task, job_service, job, plan_id: str, db) -> di
def _cleanup_output(job_id: str) -> None:
"""清理临时输出文件。"""
try:
_output_dir = os.environ.get(
"VIDEO_OUTPUT_DIR", os.path.join(tempfile.gettempdir(), "video_output")
)
_output_dir = os.environ.get("VIDEO_OUTPUT_DIR", os.path.join(tempfile.gettempdir(), "video_output"))
output_path = os.path.join(_output_dir, f"{job_id}.mp4")
if Path(output_path).exists():
Path(output_path).unlink()
@@ -84,9 +84,7 @@ class FeatureFlagConfig:
# 基于 identifier 做哈希取模,确保同一用户始终落在同一侧
if identifier:
hash_val = int(
hashlib.md5(f"{self.name}:{identifier}".encode("utf-8")).hexdigest(), 16
)
hash_val = int(hashlib.md5(f"{self.name}:{identifier}".encode("utf-8")).hexdigest(), 16)
return (hash_val % 100) < self.percentage
# 无 identifier 且百分比在 0-100 之间 → 按比例随机(不保证一致性)
@@ -158,9 +156,7 @@ class RedisFeatureFlagStore(FeatureFlagStore):
Fields: enabled, percentage, whitelist(JSON array)
"""
def __init__(
self, redis_url: str, key_prefix: str = FEATURE_FLAG_REDIS_PREFIX
) -> None:
def __init__(self, redis_url: str, key_prefix: str = FEATURE_FLAG_REDIS_PREFIX) -> None:
import redis as redis_lib
self._redis = redis_lib.from_url(redis_url, decode_responses=True)
@@ -242,9 +238,7 @@ class RedisFeatureFlagStore(FeatureFlagStore):
try:
cursor = 0
while True:
cursor, keys = self._redis.scan(
cursor=cursor, match=pattern, count=100
)
cursor, keys = self._redis.scan(cursor=cursor, match=pattern, count=100)
for key in keys:
name = key[len(self._key_prefix) :]
result[name] = self.get(name)
+3 -11
View File
@@ -146,9 +146,7 @@ class TestInMemoryFeatureFlagStore:
def test_set_and_get(self):
"""设置后可以读取。"""
store = InMemoryFeatureFlagStore()
config = FeatureFlagConfig(
name="test", enabled=True, percentage=50, whitelist={"u1"}
)
config = FeatureFlagConfig(name="test", enabled=True, percentage=50, whitelist={"u1"})
store.set(config)
got = store.get("test")
@@ -183,11 +181,7 @@ class TestInMemoryFeatureFlagStore:
def test_is_active_convenience(self):
"""is_active 便捷方法。"""
store = InMemoryFeatureFlagStore()
store.set(
FeatureFlagConfig(
name="render", enabled=True, percentage=0, whitelist={"vip_user"}
)
)
store.set(FeatureFlagConfig(name="render", enabled=True, percentage=0, whitelist={"vip_user"}))
assert store.is_active("render", "vip_user") is True
assert store.is_active("render", "normal_user") is False
assert store.is_active("nonexistent") is False
@@ -283,9 +277,7 @@ class TestRenderEngineResolver:
assert resolver.get_engine("user1") == "legacy"
# 开启 100%
resolver.set_flag(
FeatureFlagConfig(name="render_engine", enabled=True, percentage=100)
)
resolver.set_flag(FeatureFlagConfig(name="render_engine", enabled=True, percentage=100))
assert resolver.get_engine("user1") == "unified"
# 关闭