99 lines
2.9 KiB
Python
99 lines
2.9 KiB
Python
"""Отложенный старт фоновых задач после create_app — разгрузка SD при boot."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
import platform
|
||
import threading
|
||
import time
|
||
from typing import Callable, Optional
|
||
|
||
_log = logging.getLogger(__name__)
|
||
|
||
|
||
def _is_arm() -> bool:
|
||
machine = platform.machine().lower()
|
||
return any(part in machine for part in ("arm", "aarch64"))
|
||
|
||
|
||
def default_startup_delay_sec(env_name: str, *, arm_default: float, other_default: float) -> float:
|
||
import os
|
||
|
||
raw = os.getenv(env_name, "").strip()
|
||
if raw:
|
||
try:
|
||
return max(0.0, float(raw))
|
||
except ValueError:
|
||
pass
|
||
return arm_default if _is_arm() else other_default
|
||
|
||
|
||
def schedule_deferred(
|
||
fn: Callable[[], None],
|
||
*,
|
||
delay_sec: float,
|
||
thread_name: str,
|
||
log_label: str = "",
|
||
) -> None:
|
||
sec = max(0.0, float(delay_sec))
|
||
label = log_label or thread_name
|
||
|
||
def _run() -> None:
|
||
if sec > 0:
|
||
_log.info("Отложенный старт через %.1f с: %s", sec, label)
|
||
time.sleep(sec)
|
||
try:
|
||
fn()
|
||
except Exception:
|
||
_log.exception("Отложенный старт: сбой (%s)", label)
|
||
|
||
threading.Thread(target=_run, daemon=True, name=thread_name).start()
|
||
|
||
|
||
def schedule_mdns_after_boot(app, *, delay_sec: Optional[float] = None) -> None:
|
||
if delay_sec is None:
|
||
delay_sec = default_startup_delay_sec(
|
||
"WESP_STARTUP_MDNS_DELAY_SEC", arm_default=10.0, other_default=2.0
|
||
)
|
||
|
||
def _start() -> None:
|
||
from app.services.mdns_service import ensure_mdns_running, schedule_mdns_retry_if_needed
|
||
|
||
if not ensure_mdns_running(app, source="boot"):
|
||
schedule_mdns_retry_if_needed(app)
|
||
|
||
schedule_deferred(_start, delay_sec=delay_sec, thread_name="wesp-mdns-defer", log_label="mDNS")
|
||
|
||
|
||
def schedule_sync_requeue_after_boot(app, *, delay_sec: Optional[float] = None) -> None:
|
||
if delay_sec is None:
|
||
delay_sec = default_startup_delay_sec(
|
||
"WESP_STARTUP_REQUEUE_DELAY_SEC", arm_default=45.0, other_default=15.0
|
||
)
|
||
|
||
def _start() -> None:
|
||
from app import _start_sync_requeue_worker
|
||
|
||
_start_sync_requeue_worker(app)
|
||
|
||
schedule_deferred(
|
||
_start, delay_sec=delay_sec, thread_name="wesp-requeue-defer", log_label="sync requeue"
|
||
)
|
||
|
||
|
||
def schedule_bootstrap_update_env(app, *, delay_sec: Optional[float] = None) -> None:
|
||
if delay_sec is None:
|
||
delay_sec = default_startup_delay_sec(
|
||
"WESP_STARTUP_BOOTSTRAP_DELAY_SEC", arm_default=2.0, other_default=0.0
|
||
)
|
||
|
||
def _run() -> None:
|
||
with app.app_context():
|
||
from app.services.auto_update_settings_service import bootstrap_update_environment
|
||
|
||
bootstrap_update_environment(app)
|
||
|
||
schedule_deferred(
|
||
_run, delay_sec=delay_sec, thread_name="wesp-bootstrap-defer", log_label="OTA bootstrap"
|
||
)
|