- Change SQLite database path from `/home/oib/windsurf/aitbc/data/` to `/opt/data/` - Fix foreign key references to use correct table names (users, wallets, gpu_registry) - Replace governance router with new governance and community routers - Add multi-modal RL router to main application - Simplify DEPLOYMENT_READINESS_REPORT.md to focus on production deployment status - Update governance router with decentralized DAO voting
178 lines
6.5 KiB
Python
178 lines
6.5 KiB
Python
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
from prometheus_client import make_asgi_app
|
|
|
|
from .config import settings
|
|
from .storage import init_db
|
|
from .routers import (
|
|
client,
|
|
miner,
|
|
admin,
|
|
marketplace,
|
|
marketplace_gpu,
|
|
exchange,
|
|
users,
|
|
services,
|
|
marketplace_offers,
|
|
zk_applications,
|
|
explorer,
|
|
payments,
|
|
web_vitals,
|
|
edge_gpu
|
|
)
|
|
from .routers.ml_zk_proofs import router as ml_zk_proofs
|
|
from .routers.community import router as community_router
|
|
from .routers.governance import router as new_governance_router
|
|
from .routers.partners import router as partners
|
|
from .routers.marketplace_enhanced_simple import router as marketplace_enhanced
|
|
from .routers.openclaw_enhanced_simple import router as openclaw_enhanced
|
|
from .routers.monitoring_dashboard import router as monitoring_dashboard
|
|
from .routers.multi_modal_rl import router as multi_modal_rl_router
|
|
from .storage.models_governance import GovernanceProposal, ProposalVote, TreasuryTransaction, GovernanceParameter
|
|
from .exceptions import AITBCError, ErrorResponse
|
|
from .logging import get_logger
|
|
from .config import settings
|
|
from .storage.db import init_db
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
app = FastAPI(
|
|
title="AITBC Coordinator API",
|
|
version="0.1.0",
|
|
description="Stage 1 coordinator service handling job orchestration between clients and miners.",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
openapi_url="/openapi.json",
|
|
openapi_tags=[
|
|
{"name": "health", "description": "Health check endpoints"},
|
|
{"name": "client", "description": "Client operations"},
|
|
{"name": "miner", "description": "Miner operations"},
|
|
{"name": "admin", "description": "Admin operations"},
|
|
{"name": "marketplace", "description": "GPU Marketplace"},
|
|
{"name": "exchange", "description": "Exchange operations"},
|
|
{"name": "governance", "description": "Governance operations"},
|
|
{"name": "zk", "description": "Zero-Knowledge proofs"},
|
|
]
|
|
)
|
|
|
|
# Create database tables
|
|
init_db()
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.allow_origins,
|
|
allow_credentials=True,
|
|
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
allow_headers=["*"] # Allow all headers for API keys and content types
|
|
)
|
|
|
|
app.include_router(client, prefix="/v1")
|
|
app.include_router(miner, prefix="/v1")
|
|
app.include_router(admin, prefix="/v1")
|
|
app.include_router(marketplace, prefix="/v1")
|
|
app.include_router(marketplace_gpu, prefix="/v1")
|
|
app.include_router(exchange, prefix="/v1")
|
|
app.include_router(users, prefix="/v1/users")
|
|
app.include_router(services, prefix="/v1")
|
|
app.include_router(payments, prefix="/v1")
|
|
app.include_router(marketplace_offers, prefix="/v1")
|
|
app.include_router(zk_applications.router, prefix="/v1")
|
|
app.include_router(new_governance_router, prefix="/v1")
|
|
app.include_router(community_router, prefix="/v1")
|
|
app.include_router(partners, prefix="/v1")
|
|
app.include_router(explorer, prefix="/v1")
|
|
app.include_router(web_vitals, prefix="/v1")
|
|
app.include_router(edge_gpu)
|
|
app.include_router(ml_zk_proofs)
|
|
app.include_router(marketplace_enhanced, prefix="/v1")
|
|
app.include_router(openclaw_enhanced, prefix="/v1")
|
|
app.include_router(monitoring_dashboard, prefix="/v1")
|
|
app.include_router(multi_modal_rl_router, prefix="/v1")
|
|
|
|
# Add Prometheus metrics endpoint
|
|
metrics_app = make_asgi_app()
|
|
app.mount("/metrics", metrics_app)
|
|
|
|
@app.exception_handler(AITBCError)
|
|
async def aitbc_error_handler(request: Request, exc: AITBCError) -> JSONResponse:
|
|
"""Handle AITBC exceptions with structured error responses."""
|
|
request_id = request.headers.get("X-Request-ID")
|
|
response = exc.to_response(request_id)
|
|
return JSONResponse(
|
|
status_code=response.error["status"],
|
|
content=response.model_dump()
|
|
)
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def validation_error_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
|
|
"""Handle FastAPI validation errors with structured error responses."""
|
|
request_id = request.headers.get("X-Request-ID")
|
|
details = []
|
|
for error in exc.errors():
|
|
details.append({
|
|
"field": ".".join(str(loc) for loc in error["loc"]),
|
|
"message": error["msg"],
|
|
"code": error["type"]
|
|
})
|
|
|
|
error_response = ErrorResponse(
|
|
error={
|
|
"code": "VALIDATION_ERROR",
|
|
"message": "Request validation failed",
|
|
"status": 422,
|
|
"details": details
|
|
},
|
|
request_id=request_id
|
|
)
|
|
return JSONResponse(
|
|
status_code=422,
|
|
content=error_response.model_dump()
|
|
)
|
|
|
|
@app.get("/v1/health", tags=["health"], summary="Service healthcheck")
|
|
async def health() -> dict[str, str]:
|
|
import sys
|
|
return {
|
|
"status": "ok",
|
|
"env": settings.app_env,
|
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
}
|
|
|
|
@app.get("/health/live", tags=["health"], summary="Liveness probe")
|
|
async def liveness() -> dict[str, str]:
|
|
import sys
|
|
return {
|
|
"status": "alive",
|
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
}
|
|
|
|
@app.get("/health/ready", tags=["health"], summary="Readiness probe")
|
|
async def readiness() -> dict[str, str]:
|
|
# Check database connectivity
|
|
try:
|
|
from .storage import get_engine
|
|
engine = get_engine()
|
|
with engine.connect() as conn:
|
|
conn.execute("SELECT 1")
|
|
import sys
|
|
return {
|
|
"status": "ready",
|
|
"database": "connected",
|
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
}
|
|
except Exception as e:
|
|
logger.error("Readiness check failed", extra={"error": str(e)})
|
|
return JSONResponse(
|
|
status_code=503,
|
|
content={"status": "not ready", "error": str(e)}
|
|
)
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|