first commit
This commit is contained in:
106
app/main.py
Normal file
106
app/main.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""FastAPI application entry point with lifespan management."""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from contextlib import asynccontextmanager
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
from fastapi import FastAPI
|
||||
from passlib.hash import bcrypt
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.config import settings
|
||||
from app.database import async_session_factory, engine
|
||||
from app.middleware import register_exception_handlers
|
||||
from app.models.user import User
|
||||
from app.scheduler import configure_scheduler, scheduler
|
||||
from app.routers.admin import router as admin_router
|
||||
from app.routers.auth import router as auth_router
|
||||
from app.routers.health import router as health_router
|
||||
from app.routers.ingestion import router as ingestion_router
|
||||
from app.routers.ohlcv import router as ohlcv_router
|
||||
from app.routers.indicators import router as indicators_router
|
||||
from app.routers.fundamentals import router as fundamentals_router
|
||||
from app.routers.scores import router as scores_router
|
||||
from app.routers.trades import router as trades_router
|
||||
from app.routers.watchlist import router as watchlist_router
|
||||
from app.routers.sentiment import router as sentiment_router
|
||||
from app.routers.sr_levels import router as sr_levels_router
|
||||
from app.routers.tickers import router as tickers_router
|
||||
|
||||
|
||||
def _configure_logging() -> None:
|
||||
"""Set up structured JSON-style logging."""
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(
|
||||
logging.Formatter(
|
||||
'{"time":"%(asctime)s","level":"%(levelname)s",'
|
||||
'"logger":"%(name)s","message":"%(message)s"}'
|
||||
)
|
||||
)
|
||||
root = logging.getLogger()
|
||||
root.handlers.clear()
|
||||
root.addHandler(handler)
|
||||
root.setLevel(settings.log_level.upper())
|
||||
|
||||
|
||||
async def _create_default_admin(session: AsyncSession) -> None:
|
||||
"""Create the default admin account if no admin user exists."""
|
||||
result = await session.execute(
|
||||
select(User).where(User.role == "admin")
|
||||
)
|
||||
if result.scalar_one_or_none() is None:
|
||||
admin = User(
|
||||
username="admin",
|
||||
password_hash=bcrypt.hash("admin"),
|
||||
role="admin",
|
||||
has_access=True,
|
||||
)
|
||||
session.add(admin)
|
||||
await session.commit()
|
||||
logging.getLogger(__name__).info("Default admin account created")
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
"""Manage startup and shutdown lifecycle."""
|
||||
logger = logging.getLogger(__name__)
|
||||
_configure_logging()
|
||||
logger.info("Starting Stock Data Backend")
|
||||
|
||||
async with async_session_factory() as session:
|
||||
await _create_default_admin(session)
|
||||
|
||||
configure_scheduler()
|
||||
scheduler.start()
|
||||
logger.info("Scheduler started")
|
||||
|
||||
yield
|
||||
|
||||
scheduler.shutdown(wait=False)
|
||||
logger.info("Scheduler stopped")
|
||||
await engine.dispose()
|
||||
logger.info("Shutting down")
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="Stock Data Backend",
|
||||
version="0.1.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
register_exception_handlers(app)
|
||||
app.include_router(health_router, prefix="/api/v1")
|
||||
app.include_router(auth_router, prefix="/api/v1")
|
||||
app.include_router(admin_router, prefix="/api/v1")
|
||||
app.include_router(tickers_router, prefix="/api/v1")
|
||||
app.include_router(ohlcv_router, prefix="/api/v1")
|
||||
app.include_router(ingestion_router, prefix="/api/v1")
|
||||
app.include_router(indicators_router, prefix="/api/v1")
|
||||
app.include_router(sr_levels_router, prefix="/api/v1")
|
||||
app.include_router(sentiment_router, prefix="/api/v1")
|
||||
app.include_router(fundamentals_router, prefix="/api/v1")
|
||||
app.include_router(scores_router, prefix="/api/v1")
|
||||
app.include_router(trades_router, prefix="/api/v1")
|
||||
app.include_router(watchlist_router, prefix="/api/v1")
|
||||
Reference in New Issue
Block a user