Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useAppDispatch, useAppSelector } from "@/app/hooks";
|
||||
import { AppDispatch } from "@/app/store";
|
||||
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
||||
import { useSelectedCalendars } from "@/utils/storage/useSelectedCalendars";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useI18n } from "twake-i18n";
|
||||
@@ -51,7 +52,9 @@ export function WebSocketGate() {
|
||||
useAppSelector((state) => state?.calendars?.templist) ?? {}
|
||||
);
|
||||
|
||||
const calendarsToRefreshRef = useRef<Map<string, any>>(new Map());
|
||||
const calendarsToRefreshRef = useRef<
|
||||
Map<string, { calendar: Calendar; type?: "temp" }>
|
||||
>(new Map());
|
||||
const calendarsToHideRef = useRef<Set<string>>(new Set());
|
||||
const debouncedUpdateFnRef = useRef<
|
||||
((dispatch: AppDispatch) => void) | undefined
|
||||
@@ -102,6 +105,7 @@ export function WebSocketGate() {
|
||||
clearReconnectTimeout();
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[scheduleReconnect, clearReconnectTimeout]
|
||||
);
|
||||
|
||||
@@ -111,6 +115,7 @@ export function WebSocketGate() {
|
||||
(error as ErrorEvent)?.message ?? error.type ?? "unknown";
|
||||
setWebSocketStatus(t("websocket.error", { error: errorMessage }));
|
||||
setWebSocketStatusSerity("error");
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const callBacks = useMemo(
|
||||
@@ -145,6 +150,7 @@ export function WebSocketGate() {
|
||||
|
||||
clearReconnectTimeout();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isSocketOpen, clearReconnectTimeout]);
|
||||
|
||||
// Manage WebSocket connection
|
||||
@@ -206,6 +212,7 @@ export function WebSocketGate() {
|
||||
abortController.abort();
|
||||
cleanup();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
isAuthenticated,
|
||||
callBacks,
|
||||
@@ -220,7 +227,7 @@ export function WebSocketGate() {
|
||||
|
||||
// If we just reconnected, force a re-sync
|
||||
if (justReconnectedRef.current && isSocketOpen) {
|
||||
console.log("Re-syncing calendars after reconnection");
|
||||
console.info("Re-syncing calendars after reconnection");
|
||||
previousCalendarListRef.current = [];
|
||||
previousTempCalendarListRef.current = [];
|
||||
justReconnectedRef.current = false;
|
||||
@@ -277,6 +284,7 @@ export function WebSocketGate() {
|
||||
window.removeEventListener("online", handleOnline);
|
||||
window.removeEventListener("offline", handleOffline);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isSocketOpen, isAuthenticated, clearReconnectTimeout]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -315,6 +323,7 @@ export function WebSocketGate() {
|
||||
pingCleanupRef.current = null;
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isSocketOpen]);
|
||||
|
||||
return websocketStatus ? (
|
||||
|
||||
@@ -6,8 +6,8 @@ export async function createWebSocketConnection(
|
||||
callbacks: WebSocketCallbacks
|
||||
): Promise<WebSocketWithCleanup> {
|
||||
const wsBaseUrl =
|
||||
(window as any).WEBSOCKET_URL ??
|
||||
(window as any).CALENDAR_BASE_URL?.replace(
|
||||
window.WEBSOCKET_URL ??
|
||||
window.CALENDAR_BASE_URL?.replace(
|
||||
/^http(s)?:/,
|
||||
(_: string, s: string | undefined) => (s ? "wss:" : "ws:")
|
||||
) ??
|
||||
@@ -37,7 +37,7 @@ export async function createWebSocketConnection(
|
||||
}, CONNECTION_TIMEOUT_MS);
|
||||
|
||||
const openHandler = () => {
|
||||
console.log("WebSocket connection opened");
|
||||
console.info("WebSocket connection opened");
|
||||
clearTimeout(timeoutId);
|
||||
socket.removeEventListener(
|
||||
WS_INBOUND_EVENTS.CONNECTION_OPENED,
|
||||
@@ -73,7 +73,7 @@ export async function createWebSocketConnection(
|
||||
};
|
||||
|
||||
const closeHandler = (event: CloseEvent) => {
|
||||
console.log("WebSocket closed:", event.code, event.reason);
|
||||
console.info("WebSocket closed:", event.code, event.reason);
|
||||
cleanup();
|
||||
callbacks.onClose?.(event);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,8 @@ export interface PingCleanup {
|
||||
sendPing: () => void;
|
||||
}
|
||||
|
||||
const DEFAULT_PING_INTERVAL = (window as any).WS_PING_PERIOD_MS ?? 30000;
|
||||
const DEFAULT_PONG_TIMEOUT = (window as any).WS_PING_TIMEOUT_PERIOD_MS ?? 35000;
|
||||
const DEFAULT_PING_INTERVAL = window.WS_PING_PERIOD_MS ?? 30000;
|
||||
const DEFAULT_PONG_TIMEOUT = window.WS_PING_TIMEOUT_PERIOD_MS ?? 35000;
|
||||
|
||||
/**
|
||||
* Sets up a ping/pong mechanism to monitor WebSocket connection health
|
||||
|
||||
@@ -18,6 +18,7 @@ export function useWebSocketReconnect(
|
||||
clearTimeout(reconnectTimeoutRef.current);
|
||||
reconnectTimeoutRef.current = null;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const scheduleReconnect = useCallback(() => {
|
||||
@@ -35,7 +36,7 @@ export function useWebSocketReconnect(
|
||||
const delay = getRetryDelay(reconnectAttemptsRef.current, RECONNECT_CONFIG);
|
||||
reconnectAttemptsRef.current += 1;
|
||||
|
||||
console.log(
|
||||
console.info(
|
||||
`Scheduling WebSocket reconnection in ${Math.round(delay)}ms ` +
|
||||
`(attempt ${reconnectAttemptsRef.current}/${MAX_RECONNECT_ATTEMPTS})`
|
||||
);
|
||||
@@ -45,12 +46,13 @@ export function useWebSocketReconnect(
|
||||
reconnectTimeoutRef.current = null;
|
||||
return;
|
||||
}
|
||||
console.log(
|
||||
console.info(
|
||||
`Attempting WebSocket reconnection (attempt ${reconnectAttemptsRef.current}/${MAX_RECONNECT_ATTEMPTS})`
|
||||
);
|
||||
setShouldConnect((prev) => !prev);
|
||||
clearReconnectTimeout();
|
||||
}, delay);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [clearReconnectTimeout]);
|
||||
return { scheduleReconnect, clearReconnectTimeout };
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { AppDispatch } from "@/app/store";
|
||||
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
||||
|
||||
export interface UpdateCalendarsAccumulators {
|
||||
calendarsToRefresh: Map<string, any>;
|
||||
calendarsToRefresh: Map<string, { calendar: Calendar; type?: "temp" }>;
|
||||
calendarsToHide: Set<string>;
|
||||
debouncedUpdateFn?: (dispatch: AppDispatch) => void;
|
||||
currentDebouncePeriod?: number;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AppDispatch } from "@/app/store";
|
||||
import { store } from "@/app/store";
|
||||
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
||||
import { refreshCalendarWithSyncToken } from "@/features/Calendars/services";
|
||||
import { findCalendarById, getDisplayedCalendarRange } from "@/utils";
|
||||
import { setSelectedCalendars } from "@/utils/storage/setSelectedCalendars";
|
||||
@@ -12,7 +13,10 @@ const DEFAULT_DEBOUNCE_MS = 0;
|
||||
|
||||
function createDebouncedUpdate(
|
||||
debouncePeriodMs: number,
|
||||
getCalendarsToRefresh: () => Map<string, any>,
|
||||
getCalendarsToRefresh: () => Map<
|
||||
string,
|
||||
{ calendar: Calendar; type?: "temp" }
|
||||
>,
|
||||
getCalendarsToHide: () => Set<string>
|
||||
) {
|
||||
return debounce(
|
||||
@@ -55,8 +59,7 @@ export function updateCalendars(
|
||||
);
|
||||
accumulateCalendarsToHide(calendarsToHide, accumulators.calendarsToHide);
|
||||
|
||||
const debouncePeriod =
|
||||
(window as any).WS_DEBOUNCE_PERIOD_MS ?? DEFAULT_DEBOUNCE_MS;
|
||||
const debouncePeriod = window.WS_DEBOUNCE_PERIOD_MS ?? DEFAULT_DEBOUNCE_MS;
|
||||
|
||||
if (debouncePeriod > 0) {
|
||||
if (
|
||||
@@ -94,7 +97,7 @@ export function updateCalendars(
|
||||
function accumulateCalendarsToRefresh(
|
||||
state: ReturnType<typeof store.getState>,
|
||||
calendarPaths: Set<string>,
|
||||
calendarsToRefreshMap: Map<string, any>
|
||||
calendarsToRefreshMap: Map<string, { calendar: Calendar; type?: "temp" }>
|
||||
) {
|
||||
calendarPaths.forEach((calendarPath) => {
|
||||
const calendarId = parseCalendarPath(calendarPath);
|
||||
@@ -126,7 +129,7 @@ function accumulateCalendarsToHide(
|
||||
function processCalendarsToRefresh(
|
||||
dispatch: AppDispatch,
|
||||
currentRange: { start: Date; end: Date },
|
||||
calendarsMap: Map<string, any>
|
||||
calendarsMap: Map<string, { calendar: Calendar; type?: "temp" }>
|
||||
) {
|
||||
calendarsMap.forEach((calendar) => {
|
||||
dispatch(
|
||||
|
||||
@@ -12,5 +12,5 @@ export function registerToCalendars(
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Registered to calendars", calendarURIList);
|
||||
console.info("Registered to calendars", calendarURIList);
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ export function unregisterToCalendars(
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Unregistered to calendars", calendarURIList);
|
||||
console.info("Unregistered to calendars", calendarURIList);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user