mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 20:49:00 +08:00
fix: added auth token refresh logic in event source provider error handler
This commit is contained in:
parent
a4ed9e4d47
commit
ba33c885d5
@ -50,6 +50,8 @@ function LiveLogsContainer(): JSX.Element {
|
|||||||
handleCloseConnection,
|
handleCloseConnection,
|
||||||
initialLoading,
|
initialLoading,
|
||||||
isConnectionLoading,
|
isConnectionLoading,
|
||||||
|
isConnectionError,
|
||||||
|
reconnectDueToError,
|
||||||
} = useEventSource();
|
} = useEventSource();
|
||||||
|
|
||||||
const compositeQuery = useGetCompositeQueryParam();
|
const compositeQuery = useGetCompositeQueryParam();
|
||||||
@ -153,6 +155,24 @@ function LiveLogsContainer(): JSX.Element {
|
|||||||
handleStartNewConnection,
|
handleStartNewConnection,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
useEffect((): (() => void) | undefined => {
|
||||||
|
if (isConnectionError && reconnectDueToError && compositeQuery) {
|
||||||
|
console.log('uncaught refetch try from component', reconnectDueToError);
|
||||||
|
// Small delay to prevent immediate reconnection attempts
|
||||||
|
const reconnectTimer = setTimeout(() => {
|
||||||
|
handleStartNewConnection(compositeQuery);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return (): void => clearTimeout(reconnectTimer);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [
|
||||||
|
isConnectionError,
|
||||||
|
reconnectDueToError,
|
||||||
|
compositeQuery,
|
||||||
|
handleStartNewConnection,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prefetchedList = queryLocationState?.listQueryPayload[0]?.list;
|
const prefetchedList = queryLocationState?.listQueryPayload[0]?.list;
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import { apiV3 } from 'api/apiV1';
|
import { apiV3 } from 'api/apiV1';
|
||||||
|
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||||
|
import loginApi from 'api/user/login';
|
||||||
|
import { Logout } from 'api/utils';
|
||||||
|
import afterLogin from 'AppRoutes/utils';
|
||||||
import { ENVIRONMENT } from 'constants/env';
|
import { ENVIRONMENT } from 'constants/env';
|
||||||
import { LIVE_TAIL_HEARTBEAT_TIMEOUT } from 'constants/liveTail';
|
import { LIVE_TAIL_HEARTBEAT_TIMEOUT } from 'constants/liveTail';
|
||||||
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||||
import { EventListener, EventSourcePolyfill } from 'event-source-polyfill';
|
import { EventListener, EventSourcePolyfill } from 'event-source-polyfill';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
@ -13,14 +18,13 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import { useAppContext } from './App/App';
|
|
||||||
|
|
||||||
interface IEventSourceContext {
|
interface IEventSourceContext {
|
||||||
eventSourceInstance: EventSourcePolyfill | null;
|
eventSourceInstance: EventSourcePolyfill | null;
|
||||||
isConnectionOpen: boolean;
|
isConnectionOpen: boolean;
|
||||||
isConnectionLoading: boolean;
|
isConnectionLoading: boolean;
|
||||||
isConnectionError: boolean;
|
isConnectionError: boolean;
|
||||||
initialLoading: boolean;
|
initialLoading: boolean;
|
||||||
|
reconnectDueToError: boolean;
|
||||||
handleStartOpenConnection: (urlProps: {
|
handleStartOpenConnection: (urlProps: {
|
||||||
url?: string;
|
url?: string;
|
||||||
queryString: string;
|
queryString: string;
|
||||||
@ -35,6 +39,7 @@ const EventSourceContext = createContext<IEventSourceContext>({
|
|||||||
isConnectionLoading: false,
|
isConnectionLoading: false,
|
||||||
initialLoading: true,
|
initialLoading: true,
|
||||||
isConnectionError: false,
|
isConnectionError: false,
|
||||||
|
reconnectDueToError: false,
|
||||||
handleStartOpenConnection: () => {},
|
handleStartOpenConnection: () => {},
|
||||||
handleCloseConnection: () => {},
|
handleCloseConnection: () => {},
|
||||||
handleSetInitialLoading: () => {},
|
handleSetInitialLoading: () => {},
|
||||||
@ -47,9 +52,9 @@ export function EventSourceProvider({
|
|||||||
const [isConnectionLoading, setIsConnectionLoading] = useState<boolean>(false);
|
const [isConnectionLoading, setIsConnectionLoading] = useState<boolean>(false);
|
||||||
const [isConnectionError, setIsConnectionError] = useState<boolean>(false);
|
const [isConnectionError, setIsConnectionError] = useState<boolean>(false);
|
||||||
|
|
||||||
const [initialLoading, setInitialLoading] = useState<boolean>(true);
|
const [reconnectDueToError, setReconnectDueToError] = useState<boolean>(false);
|
||||||
|
|
||||||
const { user } = useAppContext();
|
const [initialLoading, setInitialLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
const eventSourceRef = useRef<EventSourcePolyfill | null>(null);
|
const eventSourceRef = useRef<EventSourcePolyfill | null>(null);
|
||||||
|
|
||||||
@ -63,15 +68,49 @@ export function EventSourceProvider({
|
|||||||
setInitialLoading(false);
|
setInitialLoading(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleErrorConnection: EventListener = useCallback(() => {
|
const handleErrorConnection: EventListener = useCallback(async () => {
|
||||||
setIsConnectionOpen(false);
|
setIsConnectionOpen(false);
|
||||||
setIsConnectionLoading(false);
|
setIsConnectionLoading(true);
|
||||||
setIsConnectionError(true);
|
|
||||||
setInitialLoading(false);
|
setInitialLoading(false);
|
||||||
|
|
||||||
if (!eventSourceRef.current) return;
|
try {
|
||||||
|
const response = await loginApi({
|
||||||
|
refreshToken: getLocalStorageApi(LOCALSTORAGE.REFRESH_AUTH_TOKEN) || '',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('uncaught token refresh started', { response });
|
||||||
|
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
// Update tokens in local storage
|
||||||
|
afterLogin(
|
||||||
|
response.payload.userId,
|
||||||
|
response.payload.accessJwt,
|
||||||
|
response.payload.refreshJwt,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If token refresh was successful, we'll let the component
|
||||||
|
// handle reconnection through the reconnectDueToError state
|
||||||
|
setReconnectDueToError(true);
|
||||||
|
setIsConnectionError(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If token refresh failed, logout the user
|
||||||
|
|
||||||
|
if (!eventSourceRef.current) return;
|
||||||
eventSourceRef.current.close();
|
eventSourceRef.current.close();
|
||||||
|
setIsConnectionError(true);
|
||||||
|
Logout();
|
||||||
|
} catch (error) {
|
||||||
|
// If there was an error during token refresh, we'll just
|
||||||
|
// let the component handle the error state
|
||||||
|
console.error('Error refreshing token:', error);
|
||||||
|
setIsConnectionError(true);
|
||||||
|
if (!eventSourceRef.current) return;
|
||||||
|
eventSourceRef.current.close();
|
||||||
|
Logout();
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const destroyEventSourceSession = useCallback(() => {
|
const destroyEventSourceSession = useCallback(() => {
|
||||||
@ -100,7 +139,7 @@ export function EventSourceProvider({
|
|||||||
|
|
||||||
eventSourceRef.current = new EventSourcePolyfill(eventSourceUrl, {
|
eventSourceRef.current = new EventSourcePolyfill(eventSourceUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${user?.accessJwt}`,
|
Authorization: `Bearer ${getLocalStorageApi(LOCALSTORAGE.AUTH_TOKEN)}`,
|
||||||
},
|
},
|
||||||
heartbeatTimeout: LIVE_TAIL_HEARTBEAT_TIMEOUT,
|
heartbeatTimeout: LIVE_TAIL_HEARTBEAT_TIMEOUT,
|
||||||
});
|
});
|
||||||
@ -111,7 +150,7 @@ export function EventSourceProvider({
|
|||||||
eventSourceRef.current.addEventListener('error', handleErrorConnection);
|
eventSourceRef.current.addEventListener('error', handleErrorConnection);
|
||||||
eventSourceRef.current.addEventListener('open', handleOpenConnection);
|
eventSourceRef.current.addEventListener('open', handleOpenConnection);
|
||||||
},
|
},
|
||||||
[user, handleErrorConnection, handleOpenConnection],
|
[handleErrorConnection, handleOpenConnection],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
@ -128,6 +167,7 @@ export function EventSourceProvider({
|
|||||||
isConnectionLoading,
|
isConnectionLoading,
|
||||||
isConnectionOpen,
|
isConnectionOpen,
|
||||||
initialLoading,
|
initialLoading,
|
||||||
|
reconnectDueToError,
|
||||||
handleStartOpenConnection,
|
handleStartOpenConnection,
|
||||||
handleCloseConnection,
|
handleCloseConnection,
|
||||||
handleSetInitialLoading,
|
handleSetInitialLoading,
|
||||||
@ -137,6 +177,7 @@ export function EventSourceProvider({
|
|||||||
isConnectionLoading,
|
isConnectionLoading,
|
||||||
isConnectionOpen,
|
isConnectionOpen,
|
||||||
initialLoading,
|
initialLoading,
|
||||||
|
reconnectDueToError,
|
||||||
handleStartOpenConnection,
|
handleStartOpenConnection,
|
||||||
handleCloseConnection,
|
handleCloseConnection,
|
||||||
handleSetInitialLoading,
|
handleSetInitialLoading,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user