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

@@ -1,4 +1,45 @@
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict, Field
from app.agents.state_schema import MemoirStateSchema as MemoirStateResponse
__all__ = [
"BookResponse",
"ChapterDetailResponse",
"ChapterListItemResponse",
"CoverGenerationResponse",
"ExportPdfRequest",
"ExportPdfResponse",
"ImageAssetResponse",
"MemoirStateResponse",
"NextQuestionContextResponse",
"ReadingSegmentResponse",
"SetChapterStoryOrderRequest",
"StatusMessageResponse",
"StoryOrderResponse",
"UpdateBookRequest",
]
class ImageAssetResponse(BaseModel):
placeholder: str = ""
description: str = ""
index: int = 0
status: str = "pending"
prompt: str | None = None
url: str | None = None
provider: str | None = None
style: str | None = None
size: str | None = None
error: str | None = None
retryable: bool | None = None
created_at: str | None = None
updated_at: str | None = None
class ReadingSegmentResponse(BaseModel):
story_id: str
body_markdown: str = ""
cover_asset: ImageAssetResponse | None = None
class UpdateBookRequest(BaseModel):
@@ -14,3 +55,75 @@ class SetChapterStoryOrderRequest(BaseModel):
"""按顺序绑定本章节要收录的 stories覆盖原有 chapter_story_links"""
story_ids: list[str]
class BookResponse(BaseModel):
id: str | None = None
title: str | None = None
total_pages: int | None = None
total_words: int | None = None
cover_image_url: str | None = None
has_update: bool | None = None
last_update_chapter_id: str | None = None
message: str | None = None
class StatusMessageResponse(BaseModel):
status: str
message: str | None = None
class ExportPdfResponse(BaseModel):
pdf_base64: str
filename: str
class ChapterListItemResponse(BaseModel):
model_config = ConfigDict(extra="ignore")
id: str
title: str | None = None
category: str | None = None
order_index: int | None = None
status: str = "draft"
summary: str = ""
canonical_markdown: str = ""
cover_asset: ImageAssetResponse | None = None
images: list[ImageAssetResponse] = Field(default_factory=list)
word_count: int = 0
updated_at: str | None = None
is_new: bool = False
source_segments: list[str] = Field(default_factory=list)
class ChapterDetailResponse(BaseModel):
model_config = ConfigDict(extra="ignore")
id: str
title: str | None = None
canonical_markdown: str = ""
order_index: int | None = None
status: str | None = None
category: str | None = None
images: list[ImageAssetResponse] = Field(default_factory=list)
cover_asset: ImageAssetResponse | None = None
reading_segments: list[ReadingSegmentResponse] = Field(default_factory=list)
updated_at: str | None = None
is_new: bool = False
source_segments: list[str] = Field(default_factory=list)
class CoverGenerationResponse(BaseModel):
triggered: list[str] = Field(default_factory=list)
class StoryOrderResponse(BaseModel):
status: str
chapter_id: str
story_count: int
class NextQuestionContextResponse(BaseModel):
current_stage: str | None = None
empty_slots: list[str] = Field(default_factory=list)
covered_stages: list[str] = Field(default_factory=list)