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 time
|
||||||
import uuid
|
import uuid
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Any, Literal, Optional
|
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")
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
||||||
log = logging.getLogger("memory-gateway")
|
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)
|
qdrant = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY)
|
||||||
|
|
||||||
# Rate limit in-memory: {key: [timestamps]}
|
# Rate limit in-memory: {key: [timestamps]}
|
||||||
@@ -165,28 +196,6 @@ async def embed(text: str) -> list[float]:
|
|||||||
return r.json()["embeddings"][0]
|
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
|
# Endpoints
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -425,10 +434,5 @@ async def _cleanup_loop() -> None:
|
|||||||
await asyncio.sleep(3600)
|
await asyncio.sleep(3600)
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
|
||||||
async def start_cleanup() -> None:
|
|
||||||
asyncio.create_task(_cleanup_loop())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run(app, host="0.0.0.0", port=8080)
|
uvicorn.run(app, host="0.0.0.0", port=8080)
|
||||||
|
|||||||
Reference in New Issue
Block a user