"""Отложенный старт фоновых задач после 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" )