From ef94c8069bbae8e02a12cb31e87d69b56084221f Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:55:24 +0100 Subject: [PATCH 1/6] Add resourceWatcher composable --- client/src/composables/resourceWatcher.ts | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 client/src/composables/resourceWatcher.ts diff --git a/client/src/composables/resourceWatcher.ts b/client/src/composables/resourceWatcher.ts new file mode 100644 index 000000000000..a5a36671421c --- /dev/null +++ b/client/src/composables/resourceWatcher.ts @@ -0,0 +1,94 @@ +export type WatchResourceHandler = () => Promise; + +export interface WatchOptions { + /** + * Polling interval in milliseconds when the app is active (in the current tab). + */ + shortPollingInterval?: number; + /** + * Polling interval in milliseconds when the app is in the background (not in the current tab). + */ + longPollingInterval?: number; + /** + * If true, the resource is watched in the background even when the app is not active (in the current tab). + */ + enableBackgroundPolling?: boolean; +} + +const DEFAULT_WATCH_OPTIONS: WatchOptions = { + shortPollingInterval: 3000, + longPollingInterval: 10000, + enableBackgroundPolling: true, +}; + +/** + * Creates a composable that watches a resource by polling the server continuously. + * By default, the polling interval is 'short' when the app is active (in the current tab) and 'long' + * when the app is in the background (not in the current tab). + * You can also completely disable background polling by setting `enableBackgroundPolling` to false in the options. + * @param watchHandler The handler function that watches the resource by querying the server. + * @param options Options to customize the polling interval. + */ +export function useResourceWatcher(watchHandler: WatchResourceHandler, options: WatchOptions = DEFAULT_WATCH_OPTIONS) { + const { shortPollingInterval, longPollingInterval, enableBackgroundPolling } = { + ...DEFAULT_WATCH_OPTIONS, + ...options, + }; + let currentPollingInterval = shortPollingInterval; + let watchTimeout: NodeJS.Timeout | null = null; + let isEventSetup = false; + + /** + * Starts watching the resource by polling the server continuously. + */ + function startWatchingResource() { + stopWatchingResource(); + tryWatchResource(); + } + + /** + * Stops continuously watching the resource. + */ + function stopWatchingResource() { + if (watchTimeout) { + clearTimeout(watchTimeout); + watchTimeout = null; + } + } + + async function tryWatchResource() { + try { + await watchHandler(); + } catch (error) { + console.warn(error); + } finally { + if (currentPollingInterval) { + watchTimeout = setTimeout(() => { + tryWatchResource(); + }, currentPollingInterval); + } + } + } + + function setupVisibilityListeners() { + if (!isEventSetup) { + isEventSetup = true; + document.addEventListener("visibilitychange", updateThrottle); + } + } + + function updateThrottle() { + if (document.visibilityState === "visible") { + currentPollingInterval = shortPollingInterval; + startWatchingResource(); + } else { + currentPollingInterval = enableBackgroundPolling ? longPollingInterval : undefined; + } + } + + setupVisibilityListeners(); + + return { + startWatchingResource, + }; +} From e7568a2c15dec14c1979662fdd461c02e7f97690 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:59:15 +0100 Subject: [PATCH 2/6] Use resourceWatcher for notifications Now we should reduce the number of requests when the app is in background. --- client/src/entry/analysis/App.vue | 6 +++--- client/src/stores/notificationsStore.ts | 23 +++++++---------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/client/src/entry/analysis/App.vue b/client/src/entry/analysis/App.vue index f9a04516a80a..4e260de84b8a 100644 --- a/client/src/entry/analysis/App.vue +++ b/client/src/entry/analysis/App.vue @@ -173,7 +173,7 @@ export default { this.Galaxy.modal = new Modal.View(); this.Galaxy.frame = this.windowManager; if (this.Galaxy.config.enable_notification_system) { - this.startNotificationsPolling(); + this.startWatchingNotifications(); } } }, @@ -189,9 +189,9 @@ export default { } }, methods: { - startNotificationsPolling() { + startWatchingNotifications() { const notificationsStore = useNotificationsStore(); - notificationsStore.startPollingNotifications(); + notificationsStore.startWatchingNotifications(); }, openUrl(urlObj) { if (!urlObj.target) { diff --git a/client/src/stores/notificationsStore.ts b/client/src/stores/notificationsStore.ts index 589e9ce04c47..e11ed7117d29 100644 --- a/client/src/stores/notificationsStore.ts +++ b/client/src/stores/notificationsStore.ts @@ -7,19 +7,21 @@ import { loadNotificationsStatus, updateBatchNotificationsOnServer, } from "@/api/notifications"; +import { useResourceWatcher } from "@/composables/resourceWatcher"; import { mergeObjectListsById } from "@/utils/utils"; import { useBroadcastsStore } from "./broadcastsStore"; -const STATUS_POLLING_DELAY = 5000; - export const useNotificationsStore = defineStore("notificationsStore", () => { + const { startWatchingResource: startWatchingNotifications } = useResourceWatcher(getNotificationStatus, { + shortPollingInterval: 5000, + longPollingInterval: 30000, + }); const broadcastsStore = useBroadcastsStore(); const totalUnreadCount = ref(0); const notifications = ref([]); - const pollId = ref(undefined); const loadingNotifications = ref(false); const lastNotificationUpdate = ref(null); @@ -31,7 +33,6 @@ export const useNotificationsStore = defineStore("notificationsStore", () => { } async function getNotificationStatus() { - stopPollingNotifications(); try { if (!lastNotificationUpdate.value) { loadingNotifications.value = true; @@ -56,22 +57,12 @@ export const useNotificationsStore = defineStore("notificationsStore", () => { } } - async function startPollingNotifications() { - await getNotificationStatus(); - pollId.value = setTimeout(() => startPollingNotifications(), STATUS_POLLING_DELAY); - } - - function stopPollingNotifications() { - clearTimeout(pollId.value); - pollId.value = undefined; - } - async function updateBatchNotification(request: UserNotificationsBatchUpdateRequest) { await updateBatchNotificationsOnServer(request); if (request.changes.deleted) { notifications.value = notifications.value.filter((n) => !request.notification_ids.includes(n.id)); } - await startPollingNotifications(); + startWatchingNotifications(); } async function updateNotification(notification: UserNotification, changes: NotificationChanges) { @@ -85,6 +76,6 @@ export const useNotificationsStore = defineStore("notificationsStore", () => { loadingNotifications, updateNotification, updateBatchNotification, - startPollingNotifications, + startWatchingNotifications, }; }); From 40b8d980d4415fc14931e6b0dcc7c1b4319e547e Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:23:53 +0100 Subject: [PATCH 3/6] Refactor entry point polling and use resourceWatcher Remove polling related logic from tests as it is handled by the resourceWatcher --- .../InteractiveTools/InteractiveTools.vue | 3 +-- client/src/components/Masthead/Masthead.vue | 2 +- .../ToolEntryPoints/ToolEntryPoints.vue | 8 +------ client/src/stores/entryPointStore.test.js | 11 +-------- client/src/stores/entryPointStore.ts | 23 ++++++------------- 5 files changed, 11 insertions(+), 36 deletions(-) diff --git a/client/src/components/InteractiveTools/InteractiveTools.vue b/client/src/components/InteractiveTools/InteractiveTools.vue index 007dea956f13..9cdf6d27c571 100644 --- a/client/src/components/InteractiveTools/InteractiveTools.vue +++ b/client/src/components/InteractiveTools/InteractiveTools.vue @@ -134,9 +134,8 @@ export default { this.load(); }, methods: { - ...mapActions(useEntryPointStore, ["ensurePollingEntryPoints", "removeEntryPoint"]), + ...mapActions(useEntryPointStore, ["removeEntryPoint"]), load() { - this.ensurePollingEntryPoints(); this.filter = ""; }, filtered: function (items) { diff --git a/client/src/components/Masthead/Masthead.vue b/client/src/components/Masthead/Masthead.vue index 21f44f39fe72..be4006a6e4bf 100644 --- a/client/src/components/Masthead/Masthead.vue +++ b/client/src/components/Masthead/Masthead.vue @@ -89,7 +89,7 @@ watch( /* lifecyle */ onBeforeMount(() => { entryPointStore = useEntryPointStore(); - entryPointStore.ensurePollingEntryPoints(); + entryPointStore.startWatchingEntryPoints(); entryPointStore.$subscribe((mutation, state) => { updateVisibility(state.entryPoints.length > 0); }); diff --git a/client/src/components/ToolEntryPoints/ToolEntryPoints.vue b/client/src/components/ToolEntryPoints/ToolEntryPoints.vue index ead83b63c419..e1e6525eac4f 100644 --- a/client/src/components/ToolEntryPoints/ToolEntryPoints.vue +++ b/client/src/components/ToolEntryPoints/ToolEntryPoints.vue @@ -41,7 +41,7 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { getAppRoot } from "onload/loadConfig"; -import { mapActions, mapState } from "pinia"; +import { mapState } from "pinia"; import { useEntryPointStore } from "stores/entryPointStore"; library.add(faExternalLinkAlt); @@ -62,11 +62,5 @@ export default { return getAppRoot() + "interactivetool_entry_points/list"; }, }, - created: function () { - this.ensurePollingEntryPoints(); - }, - methods: { - ...mapActions(useEntryPointStore, ["ensurePollingEntryPoints"]), - }, }; diff --git a/client/src/stores/entryPointStore.test.js b/client/src/stores/entryPointStore.test.js index ddd9f8183f48..9c3aa5d2c08a 100644 --- a/client/src/stores/entryPointStore.test.js +++ b/client/src/stores/entryPointStore.test.js @@ -15,7 +15,7 @@ describe("stores/EntryPointStore", () => { setActivePinia(createPinia()); axiosMock.onGet("/api/entry_points", { params: { running: true } }).reply(200, testInteractiveToolsResponse); store = useEntryPointStore(); - store.ensurePollingEntryPoints(); + await store.fetchEntryPoints(); await flushPromises(); }); @@ -23,16 +23,7 @@ describe("stores/EntryPointStore", () => { axiosMock.restore(); }); - it("polls", async () => { - expect(store.entryPoints.length).toBe(2); - }); - it("stops polling", async () => { - expect(store.pollTimeout !== undefined).toBeTruthy(); - store.stopPollingEntryPoints(); - expect(store.pollTimeout === undefined).toBeTruthy(); - }); it("performs a partial update", async () => { - store.stopPollingEntryPoints(); const updateData = [ { model_class: "InteractiveToolEntryPoint", diff --git a/client/src/stores/entryPointStore.ts b/client/src/stores/entryPointStore.ts index 0c20bbcf84fc..081f29742201 100644 --- a/client/src/stores/entryPointStore.ts +++ b/client/src/stores/entryPointStore.ts @@ -3,6 +3,7 @@ import isEqual from "lodash.isequal"; import { defineStore } from "pinia"; import { computed, ref } from "vue"; +import { useResourceWatcher } from "@/composables/resourceWatcher"; import { getAppRoot } from "@/onload/loadConfig"; import { rethrowSimple } from "@/utils/simple-error"; @@ -20,7 +21,11 @@ interface EntryPoint { } export const useEntryPointStore = defineStore("entryPointStore", () => { - const pollTimeout = ref(undefined); + const { startWatchingResource: startWatchingEntryPoints } = useResourceWatcher(fetchEntryPoints, { + shortPollingInterval: 10000, + enableBackgroundPolling: false, //No need to poll when the user is not on the page + }); + const entryPoints = ref([]); const entryPointsForJob = computed(() => { @@ -32,18 +37,6 @@ export const useEntryPointStore = defineStore("entryPointStore", () => { entryPoints.value.filter((entryPoint) => entryPoint["output_datasets_ids"].includes(hdaId)); }); - async function ensurePollingEntryPoints() { - await fetchEntryPoints(); - pollTimeout.value = setTimeout(() => { - ensurePollingEntryPoints(); - }, 10000); - } - - function stopPollingEntryPoints() { - clearTimeout(pollTimeout.value); - pollTimeout.value = undefined; - } - async function fetchEntryPoints() { const url = `${getAppRoot()}api/entry_points`; const params = { running: true }; @@ -96,8 +89,6 @@ export const useEntryPointStore = defineStore("entryPointStore", () => { fetchEntryPoints, updateEntryPoints, removeEntryPoint, - pollTimeout, - ensurePollingEntryPoints, - stopPollingEntryPoints, + startWatchingEntryPoints, }; }); From c4c1d4f0670d50b32381140ae4f6c700f5a2203b Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:28:44 +0100 Subject: [PATCH 4/6] Remove unused store reference from historyWatcher --- client/src/store/historyStore/model/watchHistory.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/store/historyStore/model/watchHistory.test.js b/client/src/store/historyStore/model/watchHistory.test.js index b47213eddc19..e0984c7fe097 100644 --- a/client/src/store/historyStore/model/watchHistory.test.js +++ b/client/src/store/historyStore/model/watchHistory.test.js @@ -70,7 +70,7 @@ describe("watchHistory", () => { .replyOnce(200, historyData) .onGet(/api\/histories\/history-id\/contents?.*/) .replyOnce(200, historyItems); - await watchHistoryOnce(wrapper.vm.$store); + await watchHistoryOnce(); expect(wrapper.vm.getHistoryItems("history-id", "").length).toBe(2); expect(wrapper.vm.getHistoryItems("history-id", "second")[0].hid).toBe(2); expect(wrapper.vm.getHistoryItems("history-id", "state:ok")[0].hid).toBe(1); @@ -86,11 +86,11 @@ describe("watchHistory", () => { .onGet(`/history/current_history_json`) .replyOnce(500); - await watchHistoryOnce(wrapper.vm.$store); + await watchHistoryOnce(); expect(wrapper.vm.currentHistoryId).toBe("history-id"); expect(wrapper.vm.getHistoryItems("history-id", "").length).toBe(2); try { - await watchHistoryOnce(wrapper.vm.$store); + await watchHistoryOnce(); } catch (error) { console.log(error); expect(error.response.status).toBe(500); @@ -113,7 +113,7 @@ describe("watchHistory", () => { history_id: "history-id", }, ]); - await watchHistoryOnce(wrapper.vm.$store); + await watchHistoryOnce(); // We should have received the update and have 3 items in the history expect(wrapper.vm.getHistoryItems("history-id", "").length).toBe(3); }); From 63b58500f587fb57066c8323042fe736d964e14a Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:50:43 +0100 Subject: [PATCH 5/6] Refactor history watcher to use resourceWatcher --- .../History/CurrentHistory/HistoryPanel.vue | 4 +- .../History/adapters/HistoryPanelProxy.js | 4 +- .../store/historyStore/model/watchHistory.js | 61 ++++++------------- client/src/utils/data.js | 4 +- 4 files changed, 23 insertions(+), 50 deletions(-) diff --git a/client/src/components/History/CurrentHistory/HistoryPanel.vue b/client/src/components/History/CurrentHistory/HistoryPanel.vue index 4e9fdc2a5a1d..32cf6c822d91 100644 --- a/client/src/components/History/CurrentHistory/HistoryPanel.vue +++ b/client/src/components/History/CurrentHistory/HistoryPanel.vue @@ -9,7 +9,7 @@ import SelectedItems from "@/components/History/Content/SelectedItems"; import { HistoryFilters } from "@/components/History/HistoryFilters"; import { deleteContent, updateContentFields } from "@/components/History/model/queries"; import { Toast } from "@/composables/toast"; -import { rewatchHistory } from "@/store/historyStore/model/watchHistory"; +import { startWatchingHistory } from "@/store/historyStore/model/watchHistory"; import { type HistoryItem, useHistoryItemsStore } from "@/stores/historyItemsStore"; import { useHistoryStore } from "@/stores/historyStore"; import { type Alias, getOperatorForAlias } from "@/utils/filtering"; @@ -277,7 +277,7 @@ async function onUnhide(item: HistoryItem) { } function reloadContents() { - rewatchHistory(); + startWatchingHistory(); } function setInvisible(item: HistoryItem) { diff --git a/client/src/components/History/adapters/HistoryPanelProxy.js b/client/src/components/History/adapters/HistoryPanelProxy.js index 1ad3b8f6f966..28b95b38627f 100644 --- a/client/src/components/History/adapters/HistoryPanelProxy.js +++ b/client/src/components/History/adapters/HistoryPanelProxy.js @@ -4,7 +4,7 @@ */ import Backbone from "backbone"; import { createDatasetCollection } from "components/History/model/queries"; -import { watchHistory } from "store/historyStore/model/watchHistory"; +import { startWatchingHistory } from "store/historyStore/model/watchHistory"; import { useHistoryItemsStore } from "stores/historyItemsStore"; import { useHistoryStore } from "stores/historyStore"; @@ -26,7 +26,7 @@ export class HistoryPanelProxy { }; // start watching the history with continuous queries - watchHistory(); + startWatchingHistory(); } syncCurrentHistoryModel(currentHistory) { diff --git a/client/src/store/historyStore/model/watchHistory.js b/client/src/store/historyStore/model/watchHistory.js index 3d6a190a3a42..81ab4972ad92 100644 --- a/client/src/store/historyStore/model/watchHistory.js +++ b/client/src/store/historyStore/model/watchHistory.js @@ -13,31 +13,34 @@ import { getCurrentHistoryFromServer } from "stores/services/history.services"; import { loadSet } from "utils/setCache"; import { urlData } from "utils/url"; +import { useResourceWatcher } from "@/composables/resourceWatcher"; import { useCollectionElementsStore } from "@/stores/collectionElementsStore"; import { useDatasetStore } from "@/stores/datasetStore"; const limit = 1000; -let throttlePeriod = 3000; -let watchTimeout = null; - // last time the history has changed let lastUpdateTime = null; // last time changed history items have been requested let lastRequestDate = new Date(); -// We only want to kick this off once we're actively watching history -let watchingVisibility = false; +const { startWatchingResource: startWatchingHistory } = useResourceWatcher(watchHistory, { + shortPollingInterval: 3000, + longPollingInterval: 60000, +}); + +export { startWatchingHistory }; -function setVisibilityThrottle() { - if (document.visibilityState === "visible") { - // Poll every 3 seconds when visible - throttlePeriod = 3000; - rewatchHistory(); - } else { - // Poll every 60 seconds when hidden/backgrounded - throttlePeriod = 60000; +async function watchHistory() { + const { isWatching } = storeToRefs(useHistoryItemsStore()); + try { + isWatching.value = true; + await watchHistoryOnce(); + } catch (error) { + // error alerting the user that watch history failed + console.warn(error); + isWatching.value = false; } } @@ -46,8 +49,7 @@ export async function watchHistoryOnce() { const historyItemsStore = useHistoryItemsStore(); const datasetStore = useDatasetStore(); const collectionElementsStore = useCollectionElementsStore(); - // "Reset" watchTimeout so we don't queue up watchHistory calls in rewatchHistory. - watchTimeout = null; + // get current history const checkForUpdate = new Date(); const history = await getCurrentHistoryFromServer(lastUpdateTime); @@ -96,35 +98,6 @@ export async function watchHistoryOnce() { } } -export async function watchHistory() { - const { isWatching } = storeToRefs(useHistoryItemsStore()); - // Only set up visibility listeners once, whenever a watch is first started - if (watchingVisibility === false) { - watchingVisibility = true; - isWatching.value = watchingVisibility; - document.addEventListener("visibilitychange", setVisibilityThrottle); - } - try { - await watchHistoryOnce(); - } catch (error) { - // error alerting the user that watch history failed - console.warn(error); - watchingVisibility = false; - isWatching.value = watchingVisibility; - } finally { - watchTimeout = setTimeout(() => { - watchHistory(); - }, throttlePeriod); - } -} - -export function rewatchHistory() { - if (watchTimeout) { - clearTimeout(watchTimeout); - watchHistory(); - } -} - /** * Returns the set of history item IDs that are currently expanded in the history panel from the cache. * These content items need to retrieve detailed information when updated. diff --git a/client/src/utils/data.js b/client/src/utils/data.js index 02431121f8ac..23e958193bae 100644 --- a/client/src/utils/data.js +++ b/client/src/utils/data.js @@ -4,7 +4,7 @@ import { FilesDialog } from "components/FilesDialog"; import { useGlobalUploadModal } from "composables/globalUploadModal"; import $ from "jquery"; import { getAppRoot } from "onload/loadConfig"; -import { rewatchHistory } from "store/historyStore/model/watchHistory"; +import { startWatchingHistory } from "store/historyStore/model/watchHistory"; import Vue from "vue"; import { uploadPayload } from "@/utils/upload-payload.js"; @@ -116,5 +116,5 @@ export function refreshContentsWrapper() { // Legacy Panel Interface. no-op if using new history Galaxy?.currHistoryPanel?.refreshContents(); // Will not do anything in legacy interface - rewatchHistory(); + startWatchingHistory(); } From f2d44844c472b633db565f82187b2fae181aaa63 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:02:25 +0100 Subject: [PATCH 6/6] Update polling intervals in watchHistory, entryPointStore, and notificationsStore --- client/src/store/historyStore/model/watchHistory.js | 7 +++++-- client/src/stores/entryPointStore.ts | 6 ++++-- client/src/stores/notificationsStore.ts | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/src/store/historyStore/model/watchHistory.js b/client/src/store/historyStore/model/watchHistory.js index 81ab4972ad92..f04ceb582a69 100644 --- a/client/src/store/historyStore/model/watchHistory.js +++ b/client/src/store/historyStore/model/watchHistory.js @@ -19,6 +19,9 @@ import { useDatasetStore } from "@/stores/datasetStore"; const limit = 1000; +const ACTIVE_POLLING_INTERVAL = 3000; +const INACTIVE_POLLING_INTERVAL = 60000; + // last time the history has changed let lastUpdateTime = null; @@ -26,8 +29,8 @@ let lastUpdateTime = null; let lastRequestDate = new Date(); const { startWatchingResource: startWatchingHistory } = useResourceWatcher(watchHistory, { - shortPollingInterval: 3000, - longPollingInterval: 60000, + shortPollingInterval: ACTIVE_POLLING_INTERVAL, + longPollingInterval: INACTIVE_POLLING_INTERVAL, }); export { startWatchingHistory }; diff --git a/client/src/stores/entryPointStore.ts b/client/src/stores/entryPointStore.ts index 081f29742201..e59b6fefeeae 100644 --- a/client/src/stores/entryPointStore.ts +++ b/client/src/stores/entryPointStore.ts @@ -7,6 +7,8 @@ import { useResourceWatcher } from "@/composables/resourceWatcher"; import { getAppRoot } from "@/onload/loadConfig"; import { rethrowSimple } from "@/utils/simple-error"; +const ACTIVE_POLLING_INTERVAL = 10000; + // TODO: replace with the corresponding autogenerated model when ready interface EntryPoint { model_class: "InteractiveToolEntryPoint"; @@ -22,8 +24,8 @@ interface EntryPoint { export const useEntryPointStore = defineStore("entryPointStore", () => { const { startWatchingResource: startWatchingEntryPoints } = useResourceWatcher(fetchEntryPoints, { - shortPollingInterval: 10000, - enableBackgroundPolling: false, //No need to poll when the user is not on the page + shortPollingInterval: ACTIVE_POLLING_INTERVAL, + enableBackgroundPolling: false, // No need to poll in the background }); const entryPoints = ref([]); diff --git a/client/src/stores/notificationsStore.ts b/client/src/stores/notificationsStore.ts index e11ed7117d29..49a58eac7efc 100644 --- a/client/src/stores/notificationsStore.ts +++ b/client/src/stores/notificationsStore.ts @@ -12,10 +12,13 @@ import { mergeObjectListsById } from "@/utils/utils"; import { useBroadcastsStore } from "./broadcastsStore"; +const ACTIVE_POLLING_INTERVAL = 5000; +const INACTIVE_POLLING_INTERVAL = 30000; + export const useNotificationsStore = defineStore("notificationsStore", () => { const { startWatchingResource: startWatchingNotifications } = useResourceWatcher(getNotificationStatus, { - shortPollingInterval: 5000, - longPollingInterval: 30000, + shortPollingInterval: ACTIVE_POLLING_INTERVAL, + longPollingInterval: INACTIVE_POLLING_INTERVAL, }); const broadcastsStore = useBroadcastsStore();