refactor: unify database readiness lifecycle

This commit is contained in:
jxxghp
2026-08-21 20:07:07 +08:00
parent bb57b22975
commit dd1c4c3279
24 changed files with 592 additions and 268 deletions
+5 -5
View File
@@ -158,7 +158,7 @@ LOCAL_FRONTEND_SERVICE_SCRIPT = textwrap.dedent(
const backendHost = process.env.MOVIEPILOT_BACKEND_HOST || '127.0.0.1'
const backendPort = Number(process.env.PORT || 3001)
const frontendPort = Number(process.env.NGINX_PORT || 3000)
const backendHealthPath = '/api/v1/system/global?token=moviepilot'
const backendHealthPath = '/health/ready'
const backendHealthTimeoutMs = Number(process.env.MOVIEPILOT_FRONTEND_HEALTH_TIMEOUT_MS || 3000)
const backendHealthIntervalMs = Number(process.env.MOVIEPILOT_FRONTEND_HEALTH_INTERVAL_MS || 15000)
const backendMaxFailures = Math.max(
@@ -2099,7 +2099,7 @@ def _load_auth_site_definitions_inner() -> dict[str, Any]:
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from app.application.site.sites import SitesHelper # noqa
from app.application.site.sites import SitesHelper # pylint: disable=no-name-in-module
auth_sites = SitesHelper().get_authsites() or {}
definitions: dict[str, Any] = {}
@@ -2440,7 +2440,7 @@ def _apply_local_system_config_inner(config_payload: dict[str, Any]) -> None:
):
system_config.set(SystemConfigKey.UserSiteAuthParams, site_auth_item)
try:
from app.application.site.sites import SitesHelper # noqa
from app.application.site.sites import SitesHelper # pylint: disable=no-name-in-module
status, msg = SitesHelper().check_user(
site_auth_item.get("site"), site_auth_item.get("params")
@@ -2472,9 +2472,9 @@ def _ensure_superuser_account_inner() -> None:
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from app.runtime.config import settings
from app.application.security.access import get_password_hash
from app.application.security.token import get_password_hash
from app.db.oper.user import UserOper
from app.runtime.config import settings
username = str(settings.SUPERUSER or "").strip()
username_error = _validate_superuser_name(username)
+1 -1
View File
@@ -800,7 +800,7 @@ def wait_for_ready(container, started_at: float, timeout: float) -> float:
"-fsS",
"--max-time",
"2",
"http://127.0.0.1:3001/api/v1/system/global?token=moviepilot",
"http://127.0.0.1:3001/health/ready",
]
while time.monotonic() < deadline:
if not container_running(container):
+15 -3
View File
@@ -105,17 +105,29 @@ async def _async_noop():
return None
def _isolated_start(component, probe_app):
# 保留 readiness 所需状态转换,其余真实启动回调替换为空操作。
if component.start is None:
return None
if component.name == '数据库准备':
return lambda: lifecycle.get_application_health(
probe_app
).mark_database_ready()
return _noop
async def _probe():
lifecycle.settings.MOVIEPILOT_SAFE_MODE = {safe_mode!r}
lifecycle.init_extra = _async_noop
lifecycle.global_vars.set_loop = lambda loop: None
lifecycle.global_vars.stop_system = lambda: None
lifecycle.LoggerManager.shutdown = lambda: None
original_components = lifecycle.build_lifecycle_components(FastAPI())
probe_app = FastAPI()
original_components = lifecycle.build_lifecycle_components(probe_app)
isolated_components = tuple(
dataclasses.replace(
component,
start=_noop if component.start is not None else None,
start=_isolated_start(component, probe_app),
stop=_noop if component.stop is not None else None,
)
for component in original_components
@@ -134,7 +146,7 @@ async def _probe():
before_threads = threading.active_count()
before_tasks = len(asyncio.all_tasks())
started = time.perf_counter()
async with lifecycle.lifespan(FastAPI()):
async with lifecycle.lifespan(probe_app):
startup_ms = (time.perf_counter() - started) * 1000
started_threads = threading.active_count()
started_tasks = len(asyncio.all_tasks())