Skip to content

Navigation Menu

Sign in
Sign up

Add SSE-based notification center for background job events (#1496) - #2057

Draft
manzke wants to merge 1 commit into
main from
claude/charming-fermat-9rd3ri
Draft

Add SSE-based notification center for background job events (#1496) #2057
manzke wants to merge 1 commit into
main from
claude/charming-fermat-9rd3ri

Conversation

@manzke

@manzke manzke commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #1496 (v1 slice — see scope notes below).

Adds a preview-gated, per-user real-time notification center. Today, background jobs (Tools Service, e.g. AI OCR) only report progress to a client with an open /jobs/:jobId/progress SSE connection — closing the tab or navigating away silently loses the completion event. This adds a small, durable record of terminal job events that survives across page loads and multiple open tabs.

  • server/services/notifications/NotificationService.js — in-process event bus (notify(userId, type, data)); persists then broadcasts to any live SSE listeners.
  • server/services/notifications/NotificationStore.js — per-user JSON-file persistence (contents/data/notifications/<userId>.json, capped at 200 entries/user).
  • server/routes/notifications.jsGET /api/notifications/stream (SSE, multi-tab per user), GET /api/notifications (list), POST /:id/read, POST /read-all. Gated behind a new notifications feature flag (default off) + migration V078.
  • server/routes/toolsService/jobStore.jsnotifyClients() now also emits a notification on terminal job states only (completed/error/cancelled) — intermediate progress ticks are intentionally not persisted (too frequent, e.g. one per OCR page, to be a useful notification-list entry).
  • client/src/features/notifications/useNotifications hook (REST initial load + SSE live updates, same fetch+ReadableStream pattern as useEventSource.js for custom auth headers) and NotificationBell/NotificationPanel UI, mounted in Layout.jsx's header for authenticated users when the flag is enabled.

Deliberately out of scope for this slice (per the issue's own implementation-plan comment)

  • Durable, multi-instance storage — the original design assumed PostgreSQL ([Platform] PostgreSQL + persistence abstraction layer #1490 /[Platform] Multi-instance horizontal scaling via PostgreSQL LISTEN/NOTIFY #1499 ), which doesn't exist in this codebase yet. This ships a simple per-user JSON-file store behind the same NotificationService.notify() call sites, so swapping to a real DB later doesn't require touching producers.
  • Other event types — only background-job lifecycle events are wired up. chat.shared (no such feature exists yet) and system.announcement (no admin broadcast UI) have no producer in this PR.
  • Toast/desktop notifications — only the bell + panel; no Notification Web API integration.

Full write-up: docs/notifications-feature.md.

Test plan

  • npm run lint:fix && npm run format:fix — clean on all changed files
  • New unit tests: server/tests/NotificationStore.test.js (append/list/scope-per-user/mark-read/mark-all-read/path-traversal-rejection/200-item cap) — all pass
  • Verified server/routes/notifications.js, server/routes/toolsService/jobStore.js, and server/featureRegistry.js import cleanly with no errors
  • Manual end-to-end verification (start dev server, enable the feature flag, trigger an OCR job, confirm the bell updates) — not done in this session (no running dev environment with a configured OCR provider); would appreciate a manual smoke test before merge

🤖 Generated with Claude Code

https://claude.ai/code/session_01A8KD83dJU7XCZx1GUDD1kk


Generated by Claude Code

Adds a preview-gated per-user notification bell: background jobs (Tools
Service, e.g. AI OCR) now persist and push a notification on completion,
error, or cancellation, so users don't lose the result just because they
navigated away from the tab that started the job.
- server/services/notifications/{NotificationService,NotificationStore}.js:
 in-process event bus + per-user JSON-file persistence (v1 scope — not
 the PostgreSQL-backed store from #1490/#1499, which don't exist yet).
- server/routes/notifications.js: SSE stream (multi-tab per user) + list/
 mark-read REST endpoints, gated behind a new 'notifications' feature
 flag (default off).
- jobStore.js now emits a notification on terminal job states only
 (not per-progress-tick, to avoid flooding the notification list).
- client/src/features/notifications/: useNotifications hook + bell/panel
 UI, wired into the header for authenticated users when the flag is on.
Deliberately out of scope for this slice (see docs/notifications-feature.md):
durable multi-instance storage, chat-share/system-announcement producers,
and toast/desktop notifications.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A8KD83dJU7XCZx1GUDD1kk 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

api backend documentation Improvements or additions to documentation frontend testing ui

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

[Platform] Notification system — SSE-based notification center

2 participants

AltStyle によって変換されたページ (->オリジナル) /