diff --git a/gateway/main.py b/gateway/main.py index 5896d41..738a053 100644 --- a/gateway/main.py +++ b/gateway/main.py @@ -26,6 +26,7 @@ import os import time import uuid from collections import Counter +from contextlib import asynccontextmanager from datetime import datetime, timezone from typing import Any, Literal, Optional @@ -53,7 +54,37 @@ MAX_TEXT_LEN = int(os.environ.get("MAX_TEXT_LEN", "8000")) logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") log = logging.getLogger("memory-gateway") -app = FastAPI(title="Memory Gateway", version="2.4.0") +@asynccontextmanager +async def lifespan(_app: FastAPI): + """Startup/shutdown: crea collection e indici, avvia il cleanup periodico.""" + collections = qdrant.get_collections().collections + if not any(c.name == COLLECTION for c in collections): + qdrant.create_collection( + collection_name=COLLECTION, + vectors_config=qm.VectorParams(size=EMBED_DIM, distance=qm.Distance.COSINE), + ) + for field in ("agent_id", "project_id", "scope", "kind", "supersedes_id", "superseded_by"): + qdrant.create_payload_index( + collection_name=COLLECTION, + field_name=field, + field_schema=qm.PayloadSchemaType.KEYWORD, + ) + log.info("collection %s creata con indici", COLLECTION) + else: + log.info("collection %s già esistente", COLLECTION) + + cleanup_task = asyncio.create_task(_cleanup_loop()) + try: + yield + finally: + cleanup_task.cancel() + try: + await cleanup_task + except asyncio.CancelledError: + pass + + +app = FastAPI(title="Memory Gateway", version="2.5.0", lifespan=lifespan) qdrant = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY) # Rate limit in-memory: {key: [timestamps]} @@ -165,28 +196,6 @@ async def embed(text: str) -> list[float]: return r.json()["embeddings"][0] -# --------------------------------------------------------------------------- -# Startup: crea collection e indici se non esistono -# --------------------------------------------------------------------------- -@app.on_event("startup") -def startup() -> None: - collections = qdrant.get_collections().collections - if not any(c.name == COLLECTION for c in collections): - qdrant.create_collection( - collection_name=COLLECTION, - vectors_config=qm.VectorParams(size=EMBED_DIM, distance=qm.Distance.COSINE), - ) - for field in ("agent_id", "project_id", "scope", "kind", "supersedes_id", "superseded_by"): - qdrant.create_payload_index( - collection_name=COLLECTION, - field_name=field, - field_schema=qm.PayloadSchemaType.KEYWORD, - ) - log.info("collection %s creata con indici", COLLECTION) - else: - log.info("collection %s già esistente", COLLECTION) - - # --------------------------------------------------------------------------- # Endpoints # --------------------------------------------------------------------------- @@ -425,10 +434,5 @@ async def _cleanup_loop() -> None: await asyncio.sleep(3600) -@app.on_event("startup") -async def start_cleanup() -> None: - asyncio.create_task(_cleanup_loop()) - - if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8080)