Gate notifications SSE on enable_sse_updates

Notifications now follow the same flag as history and entry-point
updates: SSE when enable_sse_updates is true, polling against
/api/notifications/status otherwise. enable_notification_system
remains the outer gate that decides whether the system runs at all.

Update the store test to drive the SSE-vs-polling split off
enable_sse_updates, mirroring the historyStore test layout.
This commit is contained in:
mvdbeek
2026-04-28 19:15:24 +02:00
parent db07cc1298
commit f16e1558d8
2 changed files with 17 additions and 12 deletions
+9 -6
View File
@@ -50,11 +50,14 @@ const { server, http } = useServerMock();
const statusSpy = vi.fn();
function registerDefaultHandlers({ enableNotificationSystem }: { enableNotificationSystem: boolean }) {
function registerDefaultHandlers({ enableSseUpdates }: { enableSseUpdates: boolean }) {
server.use(
http.get("/api/configuration", ({ response }) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return response(200).json({ enable_notification_system: enableNotificationSystem } as any);
return response(200).json({
enable_notification_system: true,
enable_sse_updates: enableSseUpdates,
} as any);
}),
http.get("/api/notifications", ({ response }) => {
return response(200).json([SCENARIO_NOTIFICATION]);
@@ -99,9 +102,9 @@ describe("notificationsStore — config-driven SSE vs polling", () => {
vi.useRealTimers();
});
describe("when enable_notification_system is true (SSE scenario)", () => {
describe("when enable_sse_updates is true (SSE scenario)", () => {
beforeEach(() => {
registerDefaultHandlers({ enableNotificationSystem: true });
registerDefaultHandlers({ enableSseUpdates: true });
});
it("connects SSE and does not poll the status endpoint", async () => {
@@ -161,9 +164,9 @@ describe("notificationsStore — config-driven SSE vs polling", () => {
});
});
describe("when enable_notification_system is false (polling scenario)", () => {
describe("when enable_sse_updates is false (polling scenario)", () => {
beforeEach(() => {
registerDefaultHandlers({ enableNotificationSystem: false });
registerDefaultHandlers({ enableSseUpdates: false });
});
it("does not connect SSE and polls the status endpoint on the configured interval", async () => {
+8 -6
View File
@@ -113,9 +113,11 @@ export const useNotificationsStore = defineStore("notificationsStore", () => {
}
// Choose between SSE and polling based on the server config flag
// `enable_notification_system`. The `/api/events/stream` endpoint accepts
// `enable_sse_updates`. The `/api/events/stream` endpoint accepts
// connections regardless of the flag, so we cannot rely on EventSource
// connectivity to decide — config is the source of truth.
// connectivity to decide — config is the source of truth. Callers gate
// on `enable_notification_system` before reaching here, so we only have
// to pick the transport.
//
// `useResourceWatcher` is instantiated lazily because it registers a
// `visibilitychange` listener that calls `startWatchingResourceIfNeeded`
@@ -130,7 +132,7 @@ export const useNotificationsStore = defineStore("notificationsStore", () => {
const configStore = useConfigStore();
const decide = () => {
if (configStore.config?.enable_notification_system) {
if (configStore.config?.enable_sse_updates) {
sseConnect();
} else {
const { startWatchingResource: startPolling, stopWatchingResource } = useResourceWatcher(
@@ -191,9 +193,9 @@ export const useNotificationsStore = defineStore("notificationsStore", () => {
if (request.changes.deleted) {
notifications.value = notifications.value.filter((n) => !request.notification_ids.includes(n.id));
}
// If the notification system (and therefore SSE) is disabled, trigger
// a poll to refresh state after a local mutation.
if (!useConfigStore().config?.enable_notification_system) {
// When polling is the active transport, trigger a poll to refresh
// state after a local mutation. SSE delivers the update on its own.
if (!useConfigStore().config?.enable_sse_updates) {
startWatchingNotifications();
}
}