NoteServicesAPI / app /api /notes /notes_events.py
bichnhan2701's picture
update note events
c846dab
import asyncio
import json
import logging
from fastapi import APIRouter
from sse_starlette.sse import EventSourceResponse
from app.services.note_store import get_note
from app.models.enums import NoteStatus
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/notes/{note_id}/events")
async def note_events(note_id: str):
"""
Server-Sent Events endpoint:
- Push note.status whenever it changes
- Close stream when status == ready or error
"""
async def event_generator():
last_status = None
try:
while True:
note = get_note(note_id)
if not note:
# note chưa được tạo, chờ
await asyncio.sleep(0.5)
continue
status = note.get("status")
# Push only when status changes
if status != last_status:
yield {
"event": "status",
"data": json.dumps({
"note_id": note_id,
"status": status,
}),
}
last_status = status
# Terminal states → close SSE
if status in (
NoteStatus.ready,
NoteStatus.error,
):
break
# Avoid hammering Firestore
await asyncio.sleep(1.0)
except asyncio.CancelledError:
# Client disconnected (normal)
logger.info(
"[notes_events] SSE client disconnected note_id=%s",
note_id,
)
except Exception as e:
logger.exception(
"[notes_events] SSE error note_id=%s: %s",
note_id,
e,
)
yield {
"event": "error",
"data": json.dumps({
"note_id": note_id,
"status": "internal_error",
}),
}
return EventSourceResponse(
event_generator(),
ping=15, # keep-alive, tránh proxy/nginx kill connection
)