refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)

配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
This commit is contained in:
Sully
2026-05-22 13:44:50 +08:00
committed by GitHub
parent f09ae248f9
commit 53e0065e3e
298 changed files with 15247 additions and 4344 deletions

View File

@@ -6,37 +6,26 @@ enqueue 失败不回滚已提交数据,仅记录日志;依赖后续触发或
from __future__ import annotations
import threading
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, cast
import redis
from app.core.config import settings
from app.core.logging import get_logger
from app.core.memoir_pipeline_progress import merge_pipeline_run
from app.core.memory_compaction_schedule import schedule_memory_compaction_run
from app.core.redis_sync import get_sync_redis
from app.features.memoir.constants import memoir
from app.features.story.constants import story
logger = get_logger(__name__)
_redis_client: redis.Redis | None = None
_redis_lock = threading.Lock()
def _story_image_enqueue_key(story_id: str) -> str:
return f"enqueue:story-image:{story_id}"
def _get_redis() -> redis.Redis:
"""进程内复用单个 Redis 客户端,避免重复创建连接池。"""
global _redis_client
if _redis_client is None:
with _redis_lock:
if _redis_client is None:
_redis_client = redis.from_url(
settings.redis_url, decode_responses=True
)
return _redis_client
def _get_redis():
return get_sync_redis(decode_responses=True)
@dataclass
@@ -68,7 +57,7 @@ def enqueue_story_post_commit_effects(
"""
result = PostCommitResult()
r = _get_redis()
ttl = int(settings.story_image_enqueue_dedup_ttl)
ttl = int(story.image_enqueue_dedup_ttl)
if need_image and story_ids:
from app.tasks.story_image_tasks import (
@@ -131,7 +120,7 @@ def enqueue_story_post_commit_effects(
recompose_chapter as recompose_chapter_task,
)
cd = int(settings.recompose_chapter_delay_seconds)
cd = int(story.recompose_chapter_delay_seconds)
for cid in sorted(chapter_ids):
try:
rkwargs: dict[str, Any] = {}
@@ -201,13 +190,13 @@ def enqueue_story_post_commit_effects(
)
result.errors.append(f"compaction:{exc}")
if need_quality_pass and settings.memoir_quality_pass_enabled and story_ids:
if need_quality_pass and memoir.quality_pass_enabled and story_ids:
try:
from app.tasks.memoir_quality_pass_tasks import (
memoir_quality_pass as quality_pass_task,
)
cd = int(settings.memoir_quality_pass_delay_seconds)
cd = int(memoir.quality_pass_delay_seconds)
qp_ar = cast(Any, quality_pass_task).apply_async(
args=[user_id, sorted(story_ids), sorted(chapter_ids)],
kwargs={"memoir_correlation_id": memoir_correlation_id},