fix: revert broken subscriptions
This commit is contained in:
parent
906e2f194d
commit
52aff4242d
2 changed files with 111 additions and 190 deletions
|
|
@ -2,15 +2,8 @@ import { useRef, useEffect, useMemo, useState } from "react";
|
||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from "@apollo/client";
|
||||||
import * as Sentry from "@sentry/react-native";
|
import * as Sentry from "@sentry/react-native";
|
||||||
import { useNetworkState } from "~/stores";
|
import { useNetworkState } from "~/stores";
|
||||||
import { createLogger } from "~/lib/logger";
|
|
||||||
import { UI_SCOPES } from "~/lib/logger/scopes";
|
|
||||||
import useShallowMemo from "./useShallowMemo";
|
import useShallowMemo from "./useShallowMemo";
|
||||||
|
|
||||||
const hookLogger = createLogger({
|
|
||||||
module: UI_SCOPES.HOOKS,
|
|
||||||
feature: "useLatestWithSubscription",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Constants for retry configuration
|
// Constants for retry configuration
|
||||||
const MAX_RETRIES = 5;
|
const MAX_RETRIES = 5;
|
||||||
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
||||||
|
|
@ -54,15 +47,13 @@ export default function useLatestWithSubscription(
|
||||||
const retryCountRef = useRef(0);
|
const retryCountRef = useRef(0);
|
||||||
const subscriptionErrorRef = useRef(null);
|
const subscriptionErrorRef = useRef(null);
|
||||||
const timeoutIdRef = useRef(null);
|
const timeoutIdRef = useRef(null);
|
||||||
const unsubscribeRef = useRef(null);
|
|
||||||
const lastWsClosedDateRef = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentVarsHash = JSON.stringify(variables);
|
const currentVarsHash = JSON.stringify(variables);
|
||||||
if (currentVarsHash !== variableHashRef.current) {
|
if (currentVarsHash !== variableHashRef.current) {
|
||||||
hookLogger.debug("Variables changed; resetting subscription setup", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Variables changed, resetting subscription setup`,
|
||||||
});
|
);
|
||||||
highestIdRef.current = null;
|
highestIdRef.current = null;
|
||||||
variableHashRef.current = currentVarsHash;
|
variableHashRef.current = currentVarsHash;
|
||||||
initialSetupDoneRef.current = false;
|
initialSetupDoneRef.current = false;
|
||||||
|
|
@ -107,19 +98,19 @@ export default function useLatestWithSubscription(
|
||||||
(highestIdRef.current === null || highestId > highestIdRef.current)
|
(highestIdRef.current === null || highestId > highestIdRef.current)
|
||||||
) {
|
) {
|
||||||
highestIdRef.current = highestId;
|
highestIdRef.current = highestId;
|
||||||
hookLogger.debug("Updated subscription cursor to highest ID", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Updated subscription cursor to highest ID:`,
|
||||||
highestId,
|
highestId,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle empty results case - initialize with 0 to allow subscription for first item
|
// Handle empty results case - initialize with 0 to allow subscription for first item
|
||||||
if (highestIdRef.current === null) {
|
if (highestIdRef.current === null) {
|
||||||
highestIdRef.current = 0;
|
highestIdRef.current = 0;
|
||||||
hookLogger.debug("No initial items; setting subscription cursor", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] No initial items, setting subscription cursor to:`,
|
||||||
highestId: 0,
|
0,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [queryData, cursorKey, subscriptionKey]);
|
}, [queryData, cursorKey, subscriptionKey]);
|
||||||
|
|
@ -143,20 +134,12 @@ export default function useLatestWithSubscription(
|
||||||
if (!subscribeToMore) return;
|
if (!subscribeToMore) return;
|
||||||
if (highestIdRef.current === null) return; // Wait until we have the highest ID
|
if (highestIdRef.current === null) return; // Wait until we have the highest ID
|
||||||
|
|
||||||
// Track WS close events so we only react when wsClosedDate actually changes
|
|
||||||
const wsClosedDateChanged =
|
|
||||||
!!wsClosedDate && wsClosedDate !== lastWsClosedDateRef.current;
|
|
||||||
if (wsClosedDateChanged) {
|
|
||||||
lastWsClosedDateRef.current = wsClosedDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if max retries reached and we have an error
|
// Check if max retries reached and we have an error
|
||||||
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
||||||
hookLogger.error("Max retries reached; stopping subscription attempts", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Max retries (${maxRetries}) reached. Stopping subscription attempts.`,
|
||||||
maxRetries,
|
subscriptionErrorRef.current,
|
||||||
error: subscriptionErrorRef.current,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// Report to Sentry when max retries are reached
|
// Report to Sentry when max retries are reached
|
||||||
try {
|
try {
|
||||||
|
|
@ -172,24 +155,17 @@ export default function useLatestWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (sentryError) {
|
} catch (sentryError) {
|
||||||
hookLogger.error("Failed to report max-retries to Sentry", {
|
console.error("Failed to report to Sentry:", sentryError);
|
||||||
subscriptionKey,
|
|
||||||
error: sentryError,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for:
|
// Wait for:
|
||||||
// - initial setup not done yet
|
// - either initial setup not done yet
|
||||||
// - OR a new wsClosedDate (WS reconnect)
|
// - or a new wsClosedDate (WS reconnect)
|
||||||
// - OR a retry trigger
|
// - or a retry trigger
|
||||||
if (
|
if (initialSetupDoneRef.current && !wsClosedDate && retryTrigger === 0) {
|
||||||
initialSetupDoneRef.current &&
|
|
||||||
!wsClosedDateChanged &&
|
|
||||||
retryTrigger === 0
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,16 +178,6 @@ export default function useLatestWithSubscription(
|
||||||
timeoutIdRef.current = null;
|
timeoutIdRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always cleanup any existing subscription before creating a new one
|
|
||||||
if (unsubscribeRef.current) {
|
|
||||||
try {
|
|
||||||
unsubscribeRef.current();
|
|
||||||
} catch (_error) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
unsubscribeRef.current = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate backoff delay if this is a retry
|
// Calculate backoff delay if this is a retry
|
||||||
const backoffDelay =
|
const backoffDelay =
|
||||||
retryCountRef.current > 0
|
retryCountRef.current > 0
|
||||||
|
|
@ -221,13 +187,15 @@ export default function useLatestWithSubscription(
|
||||||
)
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
hookLogger.debug("Setting up subscription", {
|
const retryMessage =
|
||||||
subscriptionKey,
|
retryCountRef.current > 0
|
||||||
retryCount: retryCountRef.current,
|
? ` Retry attempt ${retryCountRef.current}/${maxRetries} after ${backoffDelay}ms delay`
|
||||||
maxRetries,
|
: "";
|
||||||
backoffDelay,
|
|
||||||
highestId: highestIdRef.current,
|
console.log(
|
||||||
});
|
`[${subscriptionKey}] Setting up subscription${retryMessage} with highestId:`,
|
||||||
|
highestIdRef.current,
|
||||||
|
);
|
||||||
|
|
||||||
// Use timeout for backoff
|
// Use timeout for backoff
|
||||||
timeoutIdRef.current = setTimeout(() => {
|
timeoutIdRef.current = setTimeout(() => {
|
||||||
|
|
@ -254,12 +222,10 @@ export default function useLatestWithSubscription(
|
||||||
maxRetries,
|
maxRetries,
|
||||||
);
|
);
|
||||||
|
|
||||||
hookLogger.warn("Subscription error", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Subscription error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||||
attempt: retryCountRef.current,
|
|
||||||
maxRetries,
|
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
|
|
||||||
// If we haven't reached max retries, trigger a retry
|
// If we haven't reached max retries, trigger a retry
|
||||||
if (retryCountRef.current < maxRetries) {
|
if (retryCountRef.current < maxRetries) {
|
||||||
|
|
@ -304,11 +270,10 @@ export default function useLatestWithSubscription(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hookLogger.debug("Received new items", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Received ${filteredNewItems.length} new items, updated highestId:`,
|
||||||
receivedCount: filteredNewItems.length,
|
highestIdRef.current,
|
||||||
highestId: highestIdRef.current,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// For latest items pattern, we prepend new items (DESC order in UI)
|
// For latest items pattern, we prepend new items (DESC order in UI)
|
||||||
return {
|
return {
|
||||||
|
|
@ -318,27 +283,30 @@ export default function useLatestWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save unsubscribe for cleanup on reruns/unmount
|
// Cleanup on unmount or re-run
|
||||||
unsubscribeRef.current = unsubscribe;
|
return () => {
|
||||||
|
console.log(`[${subscriptionKey}] Cleaning up subscription`);
|
||||||
// Note: cleanup is handled by the effect cleanup below.
|
if (timeoutIdRef.current) {
|
||||||
|
clearTimeout(timeoutIdRef.current);
|
||||||
|
timeoutIdRef.current = null;
|
||||||
|
}
|
||||||
|
unsubscribe();
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle setup errors (like malformed queries)
|
// Handle setup errors (like malformed queries)
|
||||||
hookLogger.error("Error setting up subscription", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Error setting up subscription:`,
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
subscriptionErrorRef.current = error;
|
subscriptionErrorRef.current = error;
|
||||||
|
|
||||||
// Increment retry counter but don't exceed maxRetries
|
// Increment retry counter but don't exceed maxRetries
|
||||||
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
||||||
|
|
||||||
hookLogger.warn("Subscription setup error", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Subscription setup error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||||
attempt: retryCountRef.current,
|
|
||||||
maxRetries,
|
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
|
|
||||||
// If we haven't reached max retries, trigger a retry
|
// If we haven't reached max retries, trigger a retry
|
||||||
if (retryCountRef.current < maxRetries) {
|
if (retryCountRef.current < maxRetries) {
|
||||||
|
|
@ -360,14 +328,16 @@ export default function useLatestWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (sentryError) {
|
} catch (sentryError) {
|
||||||
hookLogger.error("Failed to report setup error to Sentry", {
|
console.error("Failed to report to Sentry:", sentryError);
|
||||||
subscriptionKey,
|
|
||||||
error: sentryError,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup is handled by the effect cleanup below.
|
return () => {
|
||||||
|
if (timeoutIdRef.current) {
|
||||||
|
clearTimeout(timeoutIdRef.current);
|
||||||
|
timeoutIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}, backoffDelay);
|
}, backoffDelay);
|
||||||
|
|
||||||
|
|
@ -377,16 +347,6 @@ export default function useLatestWithSubscription(
|
||||||
clearTimeout(timeoutIdRef.current);
|
clearTimeout(timeoutIdRef.current);
|
||||||
timeoutIdRef.current = null;
|
timeoutIdRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsubscribeRef.current) {
|
|
||||||
try {
|
|
||||||
hookLogger.debug("Cleaning up subscription", { subscriptionKey });
|
|
||||||
unsubscribeRef.current();
|
|
||||||
} catch (_error) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
unsubscribeRef.current = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
skip,
|
skip,
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,8 @@ import { useRef, useEffect, useMemo, useState } from "react";
|
||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from "@apollo/client";
|
||||||
import * as Sentry from "@sentry/react-native";
|
import * as Sentry from "@sentry/react-native";
|
||||||
import { useNetworkState } from "~/stores";
|
import { useNetworkState } from "~/stores";
|
||||||
import { createLogger } from "~/lib/logger";
|
|
||||||
import { UI_SCOPES } from "~/lib/logger/scopes";
|
|
||||||
import useShallowMemo from "./useShallowMemo";
|
import useShallowMemo from "./useShallowMemo";
|
||||||
|
|
||||||
const hookLogger = createLogger({
|
|
||||||
module: UI_SCOPES.HOOKS,
|
|
||||||
feature: "useStreamQueryWithSubscription",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Constants for retry configuration
|
// Constants for retry configuration
|
||||||
const MAX_RETRIES = 5;
|
const MAX_RETRIES = 5;
|
||||||
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
||||||
|
|
@ -47,16 +40,14 @@ export default function useStreamQueryWithSubscription(
|
||||||
const retryCountRef = useRef(0);
|
const retryCountRef = useRef(0);
|
||||||
const subscriptionErrorRef = useRef(null);
|
const subscriptionErrorRef = useRef(null);
|
||||||
const timeoutIdRef = useRef(null);
|
const timeoutIdRef = useRef(null);
|
||||||
const unsubscribeRef = useRef(null);
|
|
||||||
const lastWsClosedDateRef = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentVarsHash = JSON.stringify(variables);
|
const currentVarsHash = JSON.stringify(variables);
|
||||||
if (currentVarsHash !== variableHashRef.current) {
|
if (currentVarsHash !== variableHashRef.current) {
|
||||||
hookLogger.debug("Variables changed; resetting cursor", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Variables changed, resetting cursor to initial value:`,
|
||||||
initialCursor,
|
initialCursor,
|
||||||
});
|
);
|
||||||
lastCursorRef.current = initialCursor;
|
lastCursorRef.current = initialCursor;
|
||||||
variableHashRef.current = currentVarsHash;
|
variableHashRef.current = currentVarsHash;
|
||||||
initialSetupDoneRef.current = false;
|
initialSetupDoneRef.current = false;
|
||||||
|
|
@ -108,10 +99,10 @@ export default function useStreamQueryWithSubscription(
|
||||||
const newCursor = lastItem[cursorKey];
|
const newCursor = lastItem[cursorKey];
|
||||||
|
|
||||||
lastCursorRef.current = newCursor;
|
lastCursorRef.current = newCursor;
|
||||||
hookLogger.debug("Updated subscription cursor", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Updated subscription cursor:`,
|
||||||
cursor: newCursor,
|
newCursor,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}, [queryData, cursorKey, subscriptionKey]);
|
}, [queryData, cursorKey, subscriptionKey]);
|
||||||
|
|
||||||
|
|
@ -133,20 +124,12 @@ export default function useStreamQueryWithSubscription(
|
||||||
if (skip) return; // If skipping, do nothing
|
if (skip) return; // If skipping, do nothing
|
||||||
if (!subscribeToMore) return;
|
if (!subscribeToMore) return;
|
||||||
|
|
||||||
// Track WS close events so we only react when wsClosedDate actually changes
|
|
||||||
const wsClosedDateChanged =
|
|
||||||
!!wsClosedDate && wsClosedDate !== lastWsClosedDateRef.current;
|
|
||||||
if (wsClosedDateChanged) {
|
|
||||||
lastWsClosedDateRef.current = wsClosedDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if max retries reached and we have an error - this check must be done regardless of other conditions
|
// Check if max retries reached and we have an error - this check must be done regardless of other conditions
|
||||||
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
||||||
hookLogger.error("Max retries reached; stopping subscription attempts", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Max retries (${maxRetries}) reached. Stopping subscription attempts.`,
|
||||||
maxRetries,
|
subscriptionErrorRef.current,
|
||||||
error: subscriptionErrorRef.current,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// Report to Sentry when max retries are reached
|
// Report to Sentry when max retries are reached
|
||||||
try {
|
try {
|
||||||
|
|
@ -162,24 +145,17 @@ export default function useStreamQueryWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (sentryError) {
|
} catch (sentryError) {
|
||||||
hookLogger.error("Failed to report max-retries to Sentry", {
|
console.error("Failed to report to Sentry:", sentryError);
|
||||||
subscriptionKey,
|
|
||||||
error: sentryError,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for:
|
// Wait for:
|
||||||
// - initial setup not done yet
|
// - either initial setup not done yet
|
||||||
// - OR a new wsClosedDate (WS reconnect)
|
// - or a new wsClosedDate (WS reconnect)
|
||||||
// - OR a retry trigger
|
// - or a retry trigger
|
||||||
if (
|
if (initialSetupDoneRef.current && !wsClosedDate && retryTrigger === 0) {
|
||||||
initialSetupDoneRef.current &&
|
|
||||||
!wsClosedDateChanged &&
|
|
||||||
retryTrigger === 0
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,16 +168,6 @@ export default function useStreamQueryWithSubscription(
|
||||||
timeoutIdRef.current = null;
|
timeoutIdRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always cleanup any existing subscription before creating a new one
|
|
||||||
if (unsubscribeRef.current) {
|
|
||||||
try {
|
|
||||||
unsubscribeRef.current();
|
|
||||||
} catch (_error) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
unsubscribeRef.current = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate backoff delay if this is a retry
|
// Calculate backoff delay if this is a retry
|
||||||
const backoffDelay =
|
const backoffDelay =
|
||||||
retryCountRef.current > 0
|
retryCountRef.current > 0
|
||||||
|
|
@ -211,13 +177,15 @@ export default function useStreamQueryWithSubscription(
|
||||||
)
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
hookLogger.debug("Setting up subscription", {
|
const retryMessage =
|
||||||
subscriptionKey,
|
retryCountRef.current > 0
|
||||||
retryCount: retryCountRef.current,
|
? ` Retry attempt ${retryCountRef.current}/${maxRetries} after ${backoffDelay}ms delay`
|
||||||
maxRetries,
|
: "";
|
||||||
backoffDelay,
|
|
||||||
cursor: lastCursorRef.current,
|
console.log(
|
||||||
});
|
`[${subscriptionKey}] Setting up subscription${retryMessage} with cursor:`,
|
||||||
|
lastCursorRef.current,
|
||||||
|
);
|
||||||
|
|
||||||
// Use timeout for backoff
|
// Use timeout for backoff
|
||||||
timeoutIdRef.current = setTimeout(() => {
|
timeoutIdRef.current = setTimeout(() => {
|
||||||
|
|
@ -244,12 +212,10 @@ export default function useStreamQueryWithSubscription(
|
||||||
maxRetries,
|
maxRetries,
|
||||||
);
|
);
|
||||||
|
|
||||||
hookLogger.warn("Subscription error", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Subscription error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||||
attempt: retryCountRef.current,
|
|
||||||
maxRetries,
|
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
|
|
||||||
// If we haven't reached max retries, trigger a retry
|
// If we haven't reached max retries, trigger a retry
|
||||||
if (retryCountRef.current < maxRetries) {
|
if (retryCountRef.current < maxRetries) {
|
||||||
|
|
@ -297,10 +263,10 @@ export default function useStreamQueryWithSubscription(
|
||||||
newItemCursor > lastCursorRef.current
|
newItemCursor > lastCursorRef.current
|
||||||
) {
|
) {
|
||||||
lastCursorRef.current = newItemCursor;
|
lastCursorRef.current = newItemCursor;
|
||||||
hookLogger.debug("Received item; cursor advanced", {
|
console.log(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] New message received with cursor:`,
|
||||||
cursor: lastCursorRef.current,
|
lastCursorRef.current,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existing = itemMap.get(item[uniqKey]);
|
const existing = itemMap.get(item[uniqKey]);
|
||||||
|
|
@ -323,27 +289,30 @@ export default function useStreamQueryWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save unsubscribe for cleanup on reruns/unmount
|
// Cleanup on unmount or re-run
|
||||||
unsubscribeRef.current = unsubscribe;
|
return () => {
|
||||||
|
console.log(`[${subscriptionKey}] Cleaning up subscription`);
|
||||||
// Note: cleanup is handled by the effect cleanup below.
|
if (timeoutIdRef.current) {
|
||||||
|
clearTimeout(timeoutIdRef.current);
|
||||||
|
timeoutIdRef.current = null;
|
||||||
|
}
|
||||||
|
unsubscribe();
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle setup errors (like malformed queries)
|
// Handle setup errors (like malformed queries)
|
||||||
hookLogger.error("Error setting up subscription", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Error setting up subscription:`,
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
subscriptionErrorRef.current = error;
|
subscriptionErrorRef.current = error;
|
||||||
|
|
||||||
// Increment retry counter but don't exceed maxRetries
|
// Increment retry counter but don't exceed maxRetries
|
||||||
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
||||||
|
|
||||||
hookLogger.warn("Subscription setup error", {
|
console.error(
|
||||||
subscriptionKey,
|
`[${subscriptionKey}] Subscription setup error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||||
attempt: retryCountRef.current,
|
|
||||||
maxRetries,
|
|
||||||
error,
|
error,
|
||||||
});
|
);
|
||||||
|
|
||||||
// If we haven't reached max retries, trigger a retry
|
// If we haven't reached max retries, trigger a retry
|
||||||
if (retryCountRef.current < maxRetries) {
|
if (retryCountRef.current < maxRetries) {
|
||||||
|
|
@ -365,14 +334,16 @@ export default function useStreamQueryWithSubscription(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (sentryError) {
|
} catch (sentryError) {
|
||||||
hookLogger.error("Failed to report setup error to Sentry", {
|
console.error("Failed to report to Sentry:", sentryError);
|
||||||
subscriptionKey,
|
|
||||||
error: sentryError,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup is handled by the effect cleanup below.
|
return () => {
|
||||||
|
if (timeoutIdRef.current) {
|
||||||
|
clearTimeout(timeoutIdRef.current);
|
||||||
|
timeoutIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}, backoffDelay);
|
}, backoffDelay);
|
||||||
|
|
||||||
|
|
@ -382,16 +353,6 @@ export default function useStreamQueryWithSubscription(
|
||||||
clearTimeout(timeoutIdRef.current);
|
clearTimeout(timeoutIdRef.current);
|
||||||
timeoutIdRef.current = null;
|
timeoutIdRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsubscribeRef.current) {
|
|
||||||
try {
|
|
||||||
hookLogger.debug("Cleaning up subscription", { subscriptionKey });
|
|
||||||
unsubscribeRef.current();
|
|
||||||
} catch (_error) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
unsubscribeRef.current = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
skip,
|
skip,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue