Add initial work from Codex
This commit is contained in:
1
backend/microservices/bi_query/__init__.py
Normal file
1
backend/microservices/bi_query/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Read-only MSSQL query microservice."""
|
||||
85
backend/microservices/bi_query/main.py
Normal file
85
backend/microservices/bi_query/main.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import pandas as pd
|
||||
from fastapi import Depends, FastAPI, Response
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.otel import (
|
||||
TelemetryProviders,
|
||||
configure_otel,
|
||||
instrument_fastapi,
|
||||
instrument_sqlalchemy_engines,
|
||||
shutdown_otel,
|
||||
)
|
||||
from app.core.security import InternalPrincipal, require_internal_principal
|
||||
from app.db.engine import create_warehouse_engines, dispose_engines
|
||||
from app.services.warehouse_service import ReadOnlyWarehouseClient
|
||||
from microservices.common.http import current_trace_headers
|
||||
|
||||
logging.basicConfig(level=settings.log_level)
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _frame_to_rows(df: pd.DataFrame) -> list[dict]:
|
||||
rows: list[dict] = []
|
||||
for _, row in df.iterrows():
|
||||
payload: dict = {}
|
||||
for key, value in row.items():
|
||||
if hasattr(value, "isoformat"):
|
||||
payload[str(key)] = value.isoformat()
|
||||
else:
|
||||
payload[str(key)] = value
|
||||
rows.append(payload)
|
||||
return rows
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
telemetry: TelemetryProviders = configure_otel(settings)
|
||||
engines = create_warehouse_engines()
|
||||
instrument_sqlalchemy_engines(engines)
|
||||
app.state.query_client = ReadOnlyWarehouseClient(engines)
|
||||
LOGGER.info("BI query service ready with read-only MSSQL engines")
|
||||
yield
|
||||
dispose_engines(engines)
|
||||
shutdown_otel(telemetry)
|
||||
|
||||
|
||||
app = FastAPI(title="bi-query-service", version="0.1.0", lifespan=lifespan)
|
||||
instrument_fastapi(app)
|
||||
|
||||
|
||||
@app.get("/internal/health")
|
||||
def health(response: Response) -> dict:
|
||||
response.headers.update(current_trace_headers())
|
||||
return {"status": "ok", "service": "bi-query-service"}
|
||||
|
||||
|
||||
@app.get("/internal/daily-sales")
|
||||
def daily_sales(
|
||||
response: Response, _auth: InternalPrincipal = Depends(require_internal_principal)
|
||||
) -> list[dict]:
|
||||
response.headers.update(current_trace_headers())
|
||||
client: ReadOnlyWarehouseClient = app.state.query_client
|
||||
return _frame_to_rows(client.fetch_daily_sales())
|
||||
|
||||
|
||||
@app.get("/internal/product-performance")
|
||||
def product_performance(
|
||||
response: Response, _auth: InternalPrincipal = Depends(require_internal_principal)
|
||||
) -> list[dict]:
|
||||
response.headers.update(current_trace_headers())
|
||||
client: ReadOnlyWarehouseClient = app.state.query_client
|
||||
return _frame_to_rows(client.fetch_product_performance())
|
||||
|
||||
|
||||
@app.get("/internal/customer-performance")
|
||||
def customer_performance(
|
||||
response: Response, _auth: InternalPrincipal = Depends(require_internal_principal)
|
||||
) -> list[dict]:
|
||||
response.headers.update(current_trace_headers())
|
||||
client: ReadOnlyWarehouseClient = app.state.query_client
|
||||
return _frame_to_rows(client.fetch_customer_performance())
|
||||
Reference in New Issue
Block a user