Backend: - Notification model + Alembic migration - Notification service: CRUD, mark read, unread count, pending scheduled - WebSocket manager singleton for real-time push - WebSocket endpoint /ws/notifications with JWT auth via query param - APScheduler integration: periodic notification sender (every 60s), daily proactive health review job (8 AM) - AI tool: schedule_notification (immediate or scheduled) - Health review worker: analyzes user memory via Claude, creates ai_generated notifications with WebSocket push Frontend: - Notification API client + Zustand store - WebSocket hook with auto-reconnect (exponential backoff) - Notification bell in header with unread count badge + dropdown - Notifications page with type badges, mark read, mark all read - WebSocket initialized in AppLayout for app-wide real-time updates - Enabled notifications nav in sidebar - English + Russian translations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
25 lines
917 B
Python
25 lines
917 B
Python
"""Periodic job: send pending scheduled notifications via WebSocket."""
|
|
from app.database import async_session_factory
|
|
from app.services.notification_service import get_pending_scheduled, mark_as_sent
|
|
from app.services.ws_manager import manager
|
|
|
|
|
|
async def send_pending_notifications():
|
|
async with async_session_factory() as db:
|
|
pending = await get_pending_scheduled(db)
|
|
for notif in pending:
|
|
await mark_as_sent(db, notif.id)
|
|
await db.commit()
|
|
|
|
# Push via WebSocket
|
|
await manager.send_to_user(notif.user_id, {
|
|
"type": "new_notification",
|
|
"notification": {
|
|
"id": str(notif.id),
|
|
"title": notif.title,
|
|
"body": notif.body,
|
|
"type": notif.type,
|
|
"created_at": notif.created_at.isoformat(),
|
|
},
|
|
})
|