# services/tenant/app/main.py """ Tenant Service FastAPI application """ from fastapi import FastAPI from sqlalchemy import text from app.core.config import settings from app.core.database import database_manager from app.api import tenants, subscriptions, webhooks from shared.service_base import StandardFastAPIService class TenantService(StandardFastAPIService): """Tenant Service with standardized setup""" expected_migration_version = "001_initial_tenant" async def on_startup(self, app): """Custom startup logic including migration verification""" await self.verify_migrations() await super().on_startup(app) async def verify_migrations(self): """Verify database schema matches the latest migrations.""" try: async with self.database_manager.get_session() as session: result = await session.execute(text("SELECT version_num FROM alembic_version")) version = result.scalar() if version != self.expected_migration_version: self.logger.error(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}") raise RuntimeError(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}") self.logger.info(f"Migration verification successful: {version}") except Exception as e: self.logger.error(f"Migration verification failed: {e}") raise def __init__(self): # Define expected database tables for health checks tenant_expected_tables = ['tenants', 'tenant_members', 'subscriptions'] super().__init__( service_name="tenant-service", app_name="Tenant Management Service", description="Multi-tenant bakery management service", version="1.0.0", log_level=settings.LOG_LEVEL, api_prefix="/api/v1", database_manager=database_manager, expected_tables=tenant_expected_tables ) async def on_startup(self, app: FastAPI): """Custom startup logic for tenant service""" # Import models to ensure they're registered with SQLAlchemy from app.models.tenants import Tenant, TenantMember, Subscription self.logger.info("Tenant models imported successfully") async def on_shutdown(self, app: FastAPI): """Custom shutdown logic for tenant service""" # Database cleanup is handled by the base class pass def get_service_features(self): """Return tenant-specific features""" return [ "multi_tenant_management", "subscription_management", "tenant_isolation", "webhook_notifications", "member_management" ] def setup_custom_endpoints(self): """Setup custom endpoints for tenant service""" @self.app.get("/metrics") async def metrics(): """Prometheus metrics endpoint""" if self.metrics_collector: return self.metrics_collector.get_metrics() return {"metrics": "not_available"} # Create service instance service = TenantService() # Create FastAPI app with standardized setup app = service.create_app( docs_url="/docs", redoc_url="/redoc" ) # Setup standard endpoints service.setup_standard_endpoints() # Setup custom endpoints service.setup_custom_endpoints() # Include routers service.add_router(tenants.router, tags=["tenants"]) service.add_router(subscriptions.router, tags=["subscriptions"]) service.add_router(webhooks.router, tags=["webhooks"]) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)