feat: bulk acknowledge unread updates (#141)
CI / lint (pull_request) Successful in 11s
CI / build-frontend (pull_request) Successful in 5s

This commit is contained in:
timmy committed 2026-08-06 21:55:32 +00:00
1 parent cafc062b9f
commit db9e51e683
6 files changed
+246

No files matched your search

+29
View File
@@ -8,6 +8,7 @@ from fastapi import FastAPI, HTTPException, Path as PathParam
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field, PositiveInt
from src import gitea_proxy
from src.gitea_proxy import (
@@ -68,6 +69,10 @@ class ReadinessPayloadError(ValueError):
"""Raised when Gitea returns a structurally invalid readiness payload."""
class NotificationReadBatch(BaseModel):
ids: list[PositiveInt] = Field(min_length=1, max_length=50)
def _context_payload(user_data, repo_data, issues_data, prs_data) -> dict:
user_model = User(
id=user_data["id"],
@@ -424,6 +429,30 @@ async def event_stream():
)
async def _mark_notification_read_result(thread_id: int) -> tuple[int, bool]:
try:
await asyncio.wait_for(
mark_notification_read(thread_id),
timeout=NOTIFICATION_MUTATION_TIMEOUT_SECONDS,
)
except Exception:
return thread_id, False
_remove_notification_from_live_snapshot(thread_id)
return thread_id, True
@app.patch("/api/v1/notifications/read")
async def read_notifications(batch: NotificationReadBatch) -> JSONResponse:
thread_ids = list(dict.fromkeys(batch.ids))
results = await asyncio.gather(
*(_mark_notification_read_result(thread_id) for thread_id in thread_ids)
)
return JSONResponse({
"marked": [thread_id for thread_id, succeeded in results if succeeded],
"failed": [thread_id for thread_id, succeeded in results if not succeeded],
})
@app.patch("/api/v1/notifications/{thread_id}/read")
async def read_notification(thread_id: int = PathParam(gt=0)) -> JSONResponse:
try: