refactor: lifespan al posto di @app.on_event (deprecato) + bump v2.5.0
- startup (collection+indici) e cleanup task nel context manager lifespan - shutdown: cancel del cleanup task - verificato sul server: startup OK, scrittura OK (istanza di test)
This commit is contained in:
+32
-28
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user