feat(01-08): rewire app.py lifespan and deps.py to use build_pipeline

- app.py: replace inline component wiring with build_pipeline(env=cfg.env)
  - Store processor as app.state.processor (and backwards-compat pipeline_components)
  - RuntimeConfig replaces get_settings(); MAVLink stop() on shutdown
- deps.py: get_flight_processor prefers app.state.processor from lifespan
  - Falls back to build_pipeline() for test contexts without lifespan
  - Per-request repo/streamer swap preserved
This commit is contained in:
Yuzviak
2026-05-11 09:04:56 +03:00
parent 3a2e91439e
commit 0bb94da3c4
2 changed files with 45 additions and 56 deletions
+28 -48
View File
@@ -7,70 +7,50 @@ from fastapi import FastAPI
from gps_denied import __version__
from gps_denied.api.routers import flights
from gps_denied.config import get_settings
from gps_denied.config import RuntimeConfig
from gps_denied.pipeline import build_pipeline
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialise core pipeline components on startup."""
from gps_denied.core.chunk_manager import RouteChunkManager
from gps_denied.core.coordinates import CoordinateTransformer
from gps_denied.core.gpr import GlobalPlaceRecognition
from gps_denied.core.graph import FactorGraphOptimizer
from gps_denied.core.mavlink import MAVLinkBridge
from gps_denied.core.metric import MetricRefinement
from gps_denied.core.models import ModelManager
from gps_denied.core.recovery import FailureRecoveryCoordinator
from gps_denied.core.rotation import ImageRotationManager
from gps_denied.core.satellite import SatelliteDataManager
from gps_denied.core.vo import create_vo_backend
from gps_denied.schemas.eskf import ESKFConfig
from gps_denied.schemas.graph import FactorGraphConfig
"""Initialise core pipeline components on startup via build_pipeline."""
cfg = RuntimeConfig()
processor = build_pipeline(env=cfg.env, config=cfg)
settings = get_settings()
# Retrieve MAVLink bridge from processor internals for lifecycle management
mavlink = processor._mavlink
mm = ModelManager(engine_dir=str(settings.models.weights_dir))
vo = create_vo_backend(model_manager=mm)
gpr = GlobalPlaceRecognition(mm)
metric = MetricRefinement(mm)
graph = FactorGraphOptimizer(FactorGraphConfig())
chunk_mgr = RouteChunkManager(graph)
recovery = FailureRecoveryCoordinator(chunk_mgr, gpr, metric)
rotation = ImageRotationManager(mm)
coord = CoordinateTransformer()
satellite = SatelliteDataManager(tile_dir=settings.satellite.tile_dir)
mavlink = MAVLinkBridge(
connection_string=settings.mavlink.connection,
output_hz=settings.mavlink.output_hz,
telemetry_hz=settings.mavlink.telemetry_hz,
)
# ESKF config from env vars (per-airframe tuning)
eskf_config = ESKFConfig(**settings.eskf.model_dump())
# Store on app.state so deps can access them
app.state.processor = processor
app.state.config = cfg
# Keep backwards-compat key so any code reading pipeline_components still works
app.state.pipeline_components = {
"vo": vo, "gpr": gpr, "metric": metric,
"graph": graph, "recovery": recovery,
"chunk_mgr": chunk_mgr, "rotation": rotation,
"coord": coord, "satellite": satellite,
"vo": processor._vo,
"gpr": processor._gpr,
"metric": processor._metric,
"graph": processor._graph,
"recovery": processor._recovery,
"chunk_mgr": processor._chunk_mgr,
"rotation": processor._rotation,
"coord": processor._coord,
"satellite": processor._satellite,
"mavlink": mavlink,
}
app.state.eskf_config = eskf_config
app.state.eskf_config = processor._eskf_config
logger.info(
"Pipeline ready — MAVLink: %s, tiles: %s",
settings.mavlink.connection, settings.satellite.tile_dir,
"Pipeline ready — env=%s, MAVLink: %s, tiles: %s",
cfg.env, cfg.mavlink.connection, cfg.satellite.tile_dir,
)
yield
# Cleanup
try:
await mavlink.stop()
except Exception:
pass
# Cleanup MAVLink on shutdown
if mavlink is not None:
try:
await mavlink.stop()
except Exception:
pass
app.state.pipeline_components = None