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

61 lines
2.9 KiB
Markdown

---
status: Accepted
date: 2026-07-03
applyTo:
- "Fuchs/Notifications/**"
- "Fuchs/js/intranet/**"
- "Fuchs/wwwroot/web/**"
- "Fuchs/Program.cs"
supersededBy: ""
---
# 0002 — Backend notifications reach the GUI via a SignalR push to every logged-in session
## Context
Domain events (see [0001](0001-domain-events-and-notification-triggers.md))
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.