Fix Sentinel UI shutdown flow

This commit is contained in:
2026-04-29 00:28:49 +08:00
parent a4fd1cff8e
commit 0613be1d14
5 changed files with 211 additions and 37 deletions
+6 -1
View File
@@ -14,7 +14,11 @@ from sentinel_orbit_downloader.api.routes_projects import router as projects_rou
from sentinel_orbit_downloader.api.routes_regions import router as regions_router
from sentinel_orbit_downloader.api.routes_search import router as search_router
from sentinel_orbit_downloader.api.routes_settings import router as settings_router
from sentinel_orbit_downloader.core.config import configured_api_host, configured_api_port
from sentinel_orbit_downloader.core.config import (
configured_api_host,
configured_api_port,
configured_ui_shutdown_token,
)
def create_app() -> FastAPI:
@@ -23,6 +27,7 @@ def create_app() -> FastAPI:
version="0.1.0",
description="Local API for Sentinel-1 search, orbit matching, and task management.",
)
app.state.shutdown_token = configured_ui_shutdown_token()
web_root = Path(__file__).resolve().parents[1] / "web"
app.mount("/static", StaticFiles(directory=web_root), name="static")
@@ -1,14 +1,42 @@
from __future__ import annotations
from fastapi import APIRouter, Depends
import os
import signal
import time
from fastapi import APIRouter, BackgroundTasks, Depends, Header, HTTPException, Request, status
from sentinel_orbit_downloader.api.deps import get_db_path
from sentinel_orbit_downloader.api.schemas import HealthResponse
from sentinel_orbit_downloader.api.schemas import HealthResponse, MessageResponse
router = APIRouter(tags=["health"])
def _terminate_current_process() -> None:
time.sleep(0.2)
try:
os.kill(os.getpid(), signal.SIGTERM)
except Exception:
os._exit(0)
@router.get("/health", response_model=HealthResponse)
def health(db_path=Depends(get_db_path)) -> HealthResponse:
return HealthResponse(status="ok", db_path=str(db_path))
@router.post("/shutdown", response_model=MessageResponse, include_in_schema=False)
def shutdown(
background_tasks: BackgroundTasks,
request: Request,
x_s1dl_shutdown_token: str | None = Header(default=None, alias="X-S1DL-Shutdown-Token"),
) -> MessageResponse:
expected_token = getattr(request.app.state, "shutdown_token", None)
if not expected_token:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Shutdown is disabled.")
if x_s1dl_shutdown_token != expected_token:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid shutdown token.")
background_tasks.add_task(_terminate_current_process)
return MessageResponse(message="Shutdown requested.")
@@ -25,3 +25,10 @@ def configured_api_port() -> int:
if not raw:
return DEFAULT_API_PORT
return int(raw)
def configured_ui_shutdown_token() -> str | None:
raw = os.getenv("S1DL_UI_SHUTDOWN_TOKEN")
if not raw:
return None
return raw