Wire all integrations + production hardening: 15 recommendations
Integration & Wiring: - useStore/useAppState wired into App.tsx (replaces 8 useState calls) - React Router wired at app root (URL-based navigation) - SparklineChart/MetricCard/BarChart integrated into Admin + Ethics pages - useNotifications.handleWSEvent wired into WebSocket handler - Notification center dropdown in header with unread badge - Locale selector added to Settings page (6 languages) - Dashboard data fetching with 10s polling into MetricCards - File drag-and-drop support on chat area Production Hardening: - PostgresStateBackend with connection pooling (psycopg2) - App lifespan wires backend from FUSIONAGI_DB_BACKEND env (memory|sqlite|postgres) - Redis cache wired from FUSIONAGI_REDIS_URL env at startup - Multi-process uvicorn config for horizontal scaling Testing: - Playwright visual regression tests (12 stories x 2 viewports) - k6 load test script with ramp/spike/ramp-down stages - 7 new Python tests (postgres fallback, app wiring) 575 Python tests + 45 frontend tests = 620 total, 0 ruff errors. Co-Authored-By: Nakamoto, S <defi@defi-oracle.io>
This commit is contained in:
@@ -39,14 +39,52 @@ def create_app(
|
||||
# --- Lifespan (replaces deprecated on_event) ---
|
||||
@asynccontextmanager
|
||||
async def lifespan(application: FastAPI): # type: ignore[type-arg]
|
||||
"""Startup / shutdown lifecycle."""
|
||||
"""Startup / shutdown lifecycle with persistence and cache wiring."""
|
||||
adapter_inner = getattr(application.state, "llm_adapter", None)
|
||||
|
||||
# Wire persistence backend from env
|
||||
backend = None
|
||||
db_backend = os.environ.get("FUSIONAGI_DB_BACKEND", "memory")
|
||||
if db_backend == "postgres":
|
||||
dsn = os.environ.get("FUSIONAGI_POSTGRES_DSN", "postgresql://localhost/fusionagi")
|
||||
try:
|
||||
from fusionagi.core.postgres_backend import PostgresStateBackend
|
||||
backend = PostgresStateBackend(dsn=dsn)
|
||||
logger.info("Using PostgresStateBackend for persistence")
|
||||
except Exception as e:
|
||||
logger.warning("Postgres backend failed, falling back to memory", extra={"error": str(e)})
|
||||
elif db_backend == "sqlite":
|
||||
db_path = os.environ.get("FUSIONAGI_SQLITE_PATH", "fusionagi_state.db")
|
||||
try:
|
||||
from fusionagi.core.sqlite_backend import SQLiteStateBackend
|
||||
backend = SQLiteStateBackend(db_path=db_path)
|
||||
logger.info("Using SQLiteStateBackend for persistence")
|
||||
except Exception as e:
|
||||
logger.warning("SQLite backend failed, falling back to memory", extra={"error": str(e)})
|
||||
|
||||
# Wire cache backend from env
|
||||
redis_url = os.environ.get("FUSIONAGI_REDIS_URL")
|
||||
if redis_url:
|
||||
try:
|
||||
from fusionagi.api.cache import RedisCacheBackend, ResponseCache
|
||||
cache_backend = RedisCacheBackend(redis_url=redis_url)
|
||||
application.state.response_cache = ResponseCache(backend=cache_backend)
|
||||
logger.info("Using RedisCacheBackend for response cache")
|
||||
except Exception as e:
|
||||
logger.warning("Redis cache failed, using in-memory cache", extra={"error": str(e)})
|
||||
|
||||
orch, bus = default_orchestrator(adapter_inner)
|
||||
# Inject backend into orchestrator's state manager if available
|
||||
if backend is not None:
|
||||
orch._state_manager._backend = backend
|
||||
store = SessionStore()
|
||||
set_app_state(orch, bus, store)
|
||||
application.state._dvadasa_ready = True
|
||||
logger.info("FusionAGI Dvādaśa API started")
|
||||
yield
|
||||
# Cleanup
|
||||
if hasattr(backend, 'close'):
|
||||
backend.close()
|
||||
logger.info("FusionAGI Dvādaśa API shutdown")
|
||||
|
||||
app = FastAPI(
|
||||
|
||||
Reference in New Issue
Block a user