Fix Sentinel UI shutdown flow
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user