Added pulling notifications from new backend-pull-notifications service

This commit is contained in:
florian committed 2026-10-12 09:52:08 +02:00
1 parent 71ec05978b
commit 8aec7bafce
2 files changed
+60 -3

No files matched your search

+57 -3
View File
@@ -3,7 +3,7 @@ from fastapi.responses import JSONResponse
from fastapi.security.api_key import APIKeyHeader
from starlette.exceptions import HTTPException as StarletteHTTPException
from typing import Dict
from pydantic import BaseModel
from pydantic import BaseModel, Field
from validator import verify_api_key
from db_module import get_db, create_connection_pool, close_connection_pool, start_healthcheck_thread
from simple_logger_handler import setup_logger, LOG_LEVEL
@@ -14,15 +14,29 @@ from metrics_server import REQUEST_COUNTER
import asyncio
from uvicorn_logger_config import LOGGING_CONFIG
from secret_manager import cleanup_secret_files
import httpx
import os
logger = setup_logger(__name__)
api_key_header_internal = APIKeyHeader(name="X-API-Key-Internal")
PULL_SERVICE_URL = os.getenv(
"BACKEND_PULL_NOTIFICATIONS_URL",
"http://backend-pull-notifications.app-notifications.svc.cluster.local:8101",
)
MAX_PAGES = 5
class Notification(BaseModel):
receipent_user_id : int
receipent_user_id : int = Field(gt=0) #ToDo fix among all services
message : Dict
class PullResponse(BaseModel):
messages: list[dict]
count: int
has_more: bool
class PullRequest(BaseModel):
user_id: int = Field(gt=0)
@asynccontextmanager
async def lifespan(app: FastAPI):
@@ -41,6 +55,12 @@ async def lifespan(app: FastAPI):
app.state.rmq_producer = producer
logger.info("[FastAPI] RabbitMQ producer initialized.")
app.state.http_client = httpx.AsyncClient (
base_url=PULL_SERVICE_URL,
timeout=httpx.Timeout(10.0,connect=3.0)
)
logger.info("[FastAPI] HTTP client initialized.")
SECRET_PATHS = frozenset({
"/etc/secrets/db_username",
"/etc/secrets/db_password",
@@ -57,6 +77,9 @@ async def lifespan(app: FastAPI):
logger.info("Closing MySQL connection pool...")
close_connection_pool()
await app.state.http_client.aclose()
logger.info("[FastAPI] Closing Http client")
api = FastAPI(
title="Internal Notifier API",
description="API to forward messages to RabbitMQ",
@@ -104,7 +127,7 @@ async def custom_http_exception_handler(request,exc):
content={"detail": exc.detail}
)
@api.post("/internal/receive-notifications")
@api.post("/internal/receive-notifications") #ToDo fix among all services
async def receive_notifications(
notification_data: Notification,
request: Request,
@@ -121,6 +144,37 @@ async def receive_notifications(
logger.info("Successfully queued for delivery to RMQ")
return {"status": "queued"}
@api.post("/internal/pull-notifications", response_model=PullResponse)
async def pull_notifications(
pull_request: PullRequest,
request: Request,
program_name: str = Depends(verify_api_key_dependency_internal),
):
user_id = pull_request.user_id
logger.debug(f"[FastAPI] User id {user_id} is requesting messages")
client: httpx.AsyncClient = request.app.state.http_client
messages: list[dict] = []
has_more = False
try:
for _ in range(MAX_PAGES):
resp = await client.post("/internal/pull-notifications", json={"user_id": user_id})
resp.raise_for_status()
data = PullResponse.model_validate(resp.json())
messages.extend(data.messages)
has_more = data.has_more
if not has_more:
break
except (httpx.HTTPError, ValueError) as e:
logger.error(f"[FastAPI] Pull service failed for user_id={user_id}: {e!r}")
status = 504 if isinstance(e, httpx.TimeoutException) else 502
raise HTTPException(status_code=status, detail="Notification service unavailable")
logger.info(f"[FastAPI] Returning {len(messages)} message(s) for user_id={user_id}, has_more={has_more}")
return PullResponse(messages=messages, count=len(messages), has_more=has_more)
async def start_servers():
logger.debug("Starting FastAPI and metrics servers")
config_main = uvicorn.Config("main:api", host="0.0.0.0", port=8101, log_level=LOG_LEVEL.lower(), log_config=LOGGING_CONFIG)