Files
Fuchs_Intranet/Fuchs/Docs/Decisions/0002-gui-notification-delivery-signalr.md
T
Stefan 882e97509a Enhance logging in FdsSqlOptions and related classes
- Updated FdsSqlOptions to accept an optional ILogger parameter for improved error logging.
- Modified FdsMfr and FdsMfrClient classes to pass the logger instance to FdsSqlOptions.
- Added detailed error logging in various methods to capture SQL execution issues and file handling errors.
- Improved documentation for FdsSqlOptions to clarify logging behavior.
- Updated Archive class to log compression errors, enhancing traceability of failures.
- Adjusted project configuration to suppress specific warnings related to transitive dependencies.
- Added NuGet.config to define package sources for dependency management.
- Updated submodule references for OCORE and related projects.
2026-07-03 20:22:05 +02:00

2.9 KiB

status, date, applyTo, supersededBy
status date applyTo supersededBy
Accepted 2026-07-03
Fuchs/Notifications/**
Fuchs/js/intranet/**
Fuchs/wwwroot/web/**
Fuchs/Program.cs

0002 — Backend notifications reach the GUI via a SignalR push to every logged-in session

Context

Domain events (see 0001) need to reach whichever browser session(s) a user has open, in near real time, without the client polling.

Decision

  • NotificationHub (Fuchs/Notifications/NotificationHub.cs) is an [Authorize] SignalR Hub mapped at /notifications in Program.cs (app.MapHub<NotificationHub>("/notifications")).
  • EventService.PublishAsync sends every GuiNotification to _hub.Clients.All.SendAsync("notification", notification, ...). Delivery is currently broadcast to all connected (authenticated) clients, not targeted per-user — any logged-in session receives every notification.
  • Publish failures are caught and logged (_logger.LogWarning) rather than thrown — a notification-delivery failure must never fail the underlying business operation that triggered it.
  • On the client, $fis.notifications (Fuchs/js/intranet/fis_main.js) opens the SignalR connection once a logged-in useraccount_id is known, listens for the "notification" event, and calls push(notification) to render a dismissible toast into #notification_frame. The toast is styled by notification.severity ("error" vs "info"), giving failures a distinct highlighted appearance from successes.
  • GuiNotification.Severity is derived by EventService.IsFailure from the DomainEventType — failure event types render as "error", everything else as "info".

Consequences

  • Any new DomainEventType that represents a failure must be added to EventService.IsFailure or it will render as a plain info toast instead of being visually flagged.
  • Because delivery is broadcast (not user-scoped), notifications are not a substitute for private/sensitive data — Context/Message content must stay appropriate for any logged-in user to see. If per-user targeting becomes necessary, that is a new decision (SignalR groups keyed by user ID), not a silent change to this one.
  • The hub requires authentication; unauthenticated sessions never connect and never receive notifications.
  • Frontend rendering logic lives in fis_main.js/fis.js — keep the built wwwroot/web/fis.js/fis.min.js in sync via the gulp build (see CLAUDE.md Build & Test) whenever the notification client code changes.

Alternatives considered

  • Per-user SignalR groups: more correct long-term but adds group join/leave lifecycle management; deferred until a concrete need for private notifications arises.
  • Server-Sent Events / long polling: rejected — SignalR was already the chosen real-time transport and needs no extra infrastructure.