79 lines
2.0 KiB
Python
79 lines
2.0 KiB
Python
"""Состояние фоновой инициализации WESP (миграции, sklad, отложенные сервисы)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
import time
|
|
from typing import Any, Dict, Optional
|
|
|
|
_lock = threading.Lock()
|
|
_phase = "pending"
|
|
_message = "Ожидание запуска…"
|
|
_error: Optional[str] = None
|
|
_ready = False
|
|
_started_at: Optional[float] = None
|
|
_ready_at: Optional[float] = None
|
|
|
|
|
|
def _now() -> float:
|
|
return time.monotonic()
|
|
|
|
|
|
def reset_startup_state() -> None:
|
|
global _phase, _message, _error, _ready, _started_at, _ready_at
|
|
with _lock:
|
|
_phase = "pending"
|
|
_message = "Ожидание запуска…"
|
|
_error = None
|
|
_ready = False
|
|
_started_at = None
|
|
_ready_at = None
|
|
|
|
|
|
def set_startup_phase(phase: str, message: str = "") -> None:
|
|
global _phase, _message, _started_at
|
|
with _lock:
|
|
_phase = phase
|
|
if message:
|
|
_message = message
|
|
if _started_at is None:
|
|
_started_at = _now()
|
|
|
|
|
|
def mark_startup_ready(message: str = "Готово") -> None:
|
|
global _phase, _message, _ready, _ready_at
|
|
with _lock:
|
|
_phase = "ready"
|
|
_message = message
|
|
_ready = True
|
|
_ready_at = _now()
|
|
|
|
|
|
def mark_startup_failed(exc: BaseException) -> None:
|
|
global _phase, _message, _error, _ready
|
|
with _lock:
|
|
_phase = "error"
|
|
_message = "Ошибка инициализации"
|
|
_error = str(exc) or exc.__class__.__name__
|
|
_ready = False
|
|
|
|
|
|
def is_startup_ready() -> bool:
|
|
with _lock:
|
|
return _ready
|
|
|
|
|
|
def startup_status_payload() -> Dict[str, Any]:
|
|
with _lock:
|
|
elapsed = None
|
|
if _started_at is not None:
|
|
end = _ready_at if _ready and _ready_at is not None else _now()
|
|
elapsed = round(end - _started_at, 2)
|
|
return {
|
|
"ready": _ready,
|
|
"phase": _phase,
|
|
"message": _message,
|
|
"error": _error,
|
|
"elapsed_sec": elapsed,
|
|
}
|