mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
refactor: unify database readiness lifecycle
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""进程内应用健康状态。"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
|
||||
class ReadinessPhase(StrEnum):
|
||||
"""应用生命周期对公开 readiness 探针暴露的最小阶段。"""
|
||||
|
||||
STARTING = "starting"
|
||||
READY = "ready"
|
||||
STOPPING = "stopping"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class ApplicationHealth:
|
||||
"""保存单个 FastAPI 实例的数据库和生命周期就绪状态。"""
|
||||
|
||||
phase: ReadinessPhase = ReadinessPhase.STARTING
|
||||
database_ready: bool = False
|
||||
|
||||
@property
|
||||
def is_ready(self) -> bool:
|
||||
"""仅在数据库和完整生命周期均成功后返回就绪。"""
|
||||
return self.phase is ReadinessPhase.READY and self.database_ready
|
||||
|
||||
def begin_startup(self) -> None:
|
||||
"""重置一次 lifespan 启动尝试的状态。"""
|
||||
self.phase = ReadinessPhase.STARTING
|
||||
self.database_ready = False
|
||||
|
||||
def mark_database_ready(self) -> None:
|
||||
"""记录数据库迁移和 head 校验已经完成。"""
|
||||
self.database_ready = True
|
||||
|
||||
def mark_ready(self) -> None:
|
||||
"""记录所有 fail-fast 生命周期组件已经启动。"""
|
||||
if not self.database_ready:
|
||||
raise RuntimeError("数据库尚未就绪,不能发布应用 ready 状态")
|
||||
self.phase = ReadinessPhase.READY
|
||||
|
||||
def mark_failed(self) -> None:
|
||||
"""记录启动存在不可恢复失败。"""
|
||||
self.phase = ReadinessPhase.FAILED
|
||||
|
||||
def mark_stopping(self) -> None:
|
||||
"""在资源关闭前撤销 readiness。"""
|
||||
self.phase = ReadinessPhase.STOPPING
|
||||
|
||||
|
||||
def get_application_health(app: FastAPI) -> ApplicationHealth:
|
||||
"""读取应用级健康状态;为直接构造的测试应用补齐默认状态。"""
|
||||
health = getattr(app.state, "moviepilot_health", None)
|
||||
if health is None:
|
||||
health = ApplicationHealth()
|
||||
app.state.moviepilot_health = health
|
||||
return health
|
||||
Reference in New Issue
Block a user