mirror of
https://github.com/ruvnet/RuView
synced 2026-07-17 16:33:18 +00:00
81cc241b9e
The Rust port at v2/ has been the primary codebase since the rename in #427. The Python implementation at v1/ is no longer the active target; the only load-bearing path is the deterministic proof bundle at v1/data/proof/ (per ADR-011 / ADR-028 witness verification). Move the whole Python tree into archive/v1/ and document the policy in archive/README.md: no new features, bug fixes only when they affect a still-load-bearing path (currently just the proof), CI continues to verify the proof on every push and PR. Path references updated in 26 files via path-pattern sed (only matches v1/<known-child> patterns, never bare v1 or API URLs like /api/v1/). Two double-prefix typos (archive/archive/v1/) caught and hand-fixed in verify-pipeline.yml and ADR-011. Validated: - Python proof verify.py imports cleanly at archive/v1/data/proof/ (numpy/scipy still required; CI installs requirements-lock.txt from archive/v1/ now) - cargo test --workspace --no-default-features → 1,539 passed, 0 failed, 8 ignored (unaffected by Python tree relocation) - ESP32-S3 on COM7 untouched (no firmware paths changed) After-merge: contributors should re-run any local `python v1/...` commands as `python archive/v1/...` (CLAUDE.md and CHANGELOG already updated).
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() |