Major changes: - Organized Python v1 implementation into v1/ subdirectory - Created Rust workspace with 9 modular crates: - wifi-densepose-core: Core types, traits, errors - wifi-densepose-signal: CSI processing, phase sanitization, FFT - wifi-densepose-nn: Neural network inference (ONNX/Candle/tch) - wifi-densepose-api: Axum-based REST/WebSocket API - wifi-densepose-db: SQLx database layer - wifi-densepose-config: Configuration management - wifi-densepose-hardware: Hardware abstraction - wifi-densepose-wasm: WebAssembly bindings - wifi-densepose-cli: Command-line interface Documentation: - ADR-001: Workspace structure - ADR-002: Signal processing library selection - ADR-003: Neural network inference strategy - DDD domain model with bounded contexts Testing: - 69 tests passing across all crates - Signal processing: 45 tests - Neural networks: 21 tests - Core: 3 doc tests Performance targets: - 10x faster CSI processing (~0.5ms vs ~5ms) - 5x lower memory usage (~100MB vs ~500MB) - WASM support for browser deployment
117 lines
3.4 KiB
Python
117 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Main application entry point for WiFi-DensePose API
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import asyncio
|
|
import logging
|
|
import signal
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
# Add src to Python path
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
|
|
from src.config.settings import get_settings, validate_settings
|
|
from src.logger import setup_logging
|
|
from src.app import create_app
|
|
from src.services.orchestrator import ServiceOrchestrator
|
|
from src.cli import create_cli
|
|
|
|
|
|
def setup_signal_handlers(orchestrator: ServiceOrchestrator):
|
|
"""Setup signal handlers for graceful shutdown."""
|
|
def signal_handler(signum, frame):
|
|
logging.info(f"Received signal {signum}, initiating graceful shutdown...")
|
|
asyncio.create_task(orchestrator.shutdown())
|
|
sys.exit(0)
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
|
|
|
|
|
async def main():
|
|
"""Main application entry point."""
|
|
try:
|
|
# Load settings
|
|
settings = get_settings()
|
|
|
|
# Setup logging
|
|
setup_logging(settings)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
logger.info(f"Starting {settings.app_name} v{settings.version}")
|
|
logger.info(f"Environment: {settings.environment}")
|
|
|
|
# Validate settings
|
|
issues = validate_settings(settings)
|
|
if issues:
|
|
logger.error("Configuration issues found:")
|
|
for issue in issues:
|
|
logger.error(f" - {issue}")
|
|
if settings.is_production:
|
|
sys.exit(1)
|
|
else:
|
|
logger.warning("Continuing with configuration issues in development mode")
|
|
|
|
# Create service orchestrator
|
|
orchestrator = ServiceOrchestrator(settings)
|
|
|
|
# Setup signal handlers
|
|
setup_signal_handlers(orchestrator)
|
|
|
|
# Initialize services
|
|
await orchestrator.initialize()
|
|
|
|
# Create FastAPI app
|
|
app = create_app(settings, orchestrator)
|
|
|
|
# Start the application
|
|
if len(sys.argv) > 1:
|
|
# CLI mode
|
|
cli = create_cli(orchestrator)
|
|
await cli.run(sys.argv[1:])
|
|
else:
|
|
# Server mode
|
|
import uvicorn
|
|
|
|
logger.info(f"Starting server on {settings.host}:{settings.port}")
|
|
|
|
config = uvicorn.Config(
|
|
app,
|
|
host=settings.host,
|
|
port=settings.port,
|
|
reload=settings.reload and settings.is_development,
|
|
workers=settings.workers if not settings.reload else 1,
|
|
log_level=settings.log_level.lower(),
|
|
access_log=True,
|
|
use_colors=True
|
|
)
|
|
|
|
server = uvicorn.Server(config)
|
|
await server.serve()
|
|
|
|
except KeyboardInterrupt:
|
|
logger.info("Received keyboard interrupt, shutting down...")
|
|
except Exception as e:
|
|
logger.error(f"Application failed to start: {e}", exc_info=True)
|
|
sys.exit(1)
|
|
finally:
|
|
# Cleanup
|
|
if 'orchestrator' in locals():
|
|
await orchestrator.shutdown()
|
|
logger.info("Application shutdown complete")
|
|
|
|
|
|
def run():
|
|
"""Entry point for package installation."""
|
|
try:
|
|
asyncio.run(main())
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run() |