Compare commits
No commits in common. "52aff4242dd9d9db3b07d2e43cf727748c6e2eb9" and "29d7747b51d333d9b592eab31c800fcdf4d808a5" have entirely different histories.
52aff4242d
...
29d7747b51
4 changed files with 190 additions and 155 deletions
|
|
@ -16,9 +16,6 @@
|
|||
"bundle:ios:export": "./scripts/ios-export.sh",
|
||||
"bundle:ios:upload": "./scripts/ios-upload.sh",
|
||||
"bundle:ios": "yarn bundle:ios:archive && yarn bundle:ios:export",
|
||||
"bundle:ios:testflight:version": "bash ./scripts/ios-set-testflight-build-number.sh",
|
||||
"bundle:ios:testflight:archive": "yarn bundle:ios:testflight:version && yarn bundle:ios:archive",
|
||||
"bundle:ios:testflight": "yarn bundle:ios:testflight:archive && yarn bundle:ios:export && yarn bundle:ios:upload",
|
||||
"ios": "expo run:ios",
|
||||
"ios:staging": "dotenv --override -e .env.staging -- yarn run ios",
|
||||
"ios:prod": "dotenv --override -e .env.prod -- yarn run ios",
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
INFO_PLIST_PATH="$PROJECT_ROOT_DIR/ios/AlerteSecours/Info.plist"
|
||||
|
||||
if [ ! -f "$INFO_PLIST_PATH" ]; then
|
||||
echo "error: Info.plist not found at $INFO_PLIST_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate a unique version/build number for TestFlight in Europe/Paris timezone
|
||||
# This value will be used for both CFBundleShortVersionString and CFBundleVersion.
|
||||
# Format: YYYYMMDDHHMM, e.g. 202601121110 (valid as a numeric-only iOS version).
|
||||
BUILD_NUMBER="$(TZ=Europe/Paris date +%Y%m%d%H%M)"
|
||||
|
||||
echo "[ios-set-testflight-build-number] Using build number: $BUILD_NUMBER"
|
||||
|
||||
PLISTBUDDY="/usr/libexec/PlistBuddy"
|
||||
|
||||
if [ ! -x "$PLISTBUDDY" ]; then
|
||||
echo "error: $PLISTBUDDY not found or not executable. This script must run on macOS with PlistBuddy available." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set_plist_version_key() {
|
||||
local key="$1"
|
||||
# Try to set the existing key, or add it if it does not exist yet.
|
||||
if ! "$PLISTBUDDY" -c "Set :$key $BUILD_NUMBER" "$INFO_PLIST_PATH" 2>/dev/null; then
|
||||
"$PLISTBUDDY" -c "Add :$key string $BUILD_NUMBER" "$INFO_PLIST_PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
set_plist_version_key "CFBundleVersion"
|
||||
set_plist_version_key "CFBundleShortVersionString"
|
||||
|
||||
echo "[ios-set-testflight-build-number] Updated CFBundleShortVersionString and CFBundleVersion in $INFO_PLIST_PATH to $BUILD_NUMBER"
|
||||
|
||||
# Print the build number on stdout so callers can capture/log it easily.
|
||||
echo "$BUILD_NUMBER"
|
||||
|
|
@ -2,8 +2,15 @@ import { useRef, useEffect, useMemo, useState } from "react";
|
|||
import { useQuery } from "@apollo/client";
|
||||
import * as Sentry from "@sentry/react-native";
|
||||
import { useNetworkState } from "~/stores";
|
||||
import { createLogger } from "~/lib/logger";
|
||||
import { UI_SCOPES } from "~/lib/logger/scopes";
|
||||
import useShallowMemo from "./useShallowMemo";
|
||||
|
||||
const hookLogger = createLogger({
|
||||
module: UI_SCOPES.HOOKS,
|
||||
feature: "useLatestWithSubscription",
|
||||
});
|
||||
|
||||
// Constants for retry configuration
|
||||
const MAX_RETRIES = 5;
|
||||
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
||||
|
|
@ -47,13 +54,15 @@ export default function useLatestWithSubscription(
|
|||
const retryCountRef = useRef(0);
|
||||
const subscriptionErrorRef = useRef(null);
|
||||
const timeoutIdRef = useRef(null);
|
||||
const unsubscribeRef = useRef(null);
|
||||
const lastWsClosedDateRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const currentVarsHash = JSON.stringify(variables);
|
||||
if (currentVarsHash !== variableHashRef.current) {
|
||||
console.log(
|
||||
`[${subscriptionKey}] Variables changed, resetting subscription setup`,
|
||||
);
|
||||
hookLogger.debug("Variables changed; resetting subscription setup", {
|
||||
subscriptionKey,
|
||||
});
|
||||
highestIdRef.current = null;
|
||||
variableHashRef.current = currentVarsHash;
|
||||
initialSetupDoneRef.current = false;
|
||||
|
|
@ -98,19 +107,19 @@ export default function useLatestWithSubscription(
|
|||
(highestIdRef.current === null || highestId > highestIdRef.current)
|
||||
) {
|
||||
highestIdRef.current = highestId;
|
||||
console.log(
|
||||
`[${subscriptionKey}] Updated subscription cursor to highest ID:`,
|
||||
hookLogger.debug("Updated subscription cursor to highest ID", {
|
||||
subscriptionKey,
|
||||
highestId,
|
||||
);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Handle empty results case - initialize with 0 to allow subscription for first item
|
||||
if (highestIdRef.current === null) {
|
||||
highestIdRef.current = 0;
|
||||
console.log(
|
||||
`[${subscriptionKey}] No initial items, setting subscription cursor to:`,
|
||||
0,
|
||||
);
|
||||
hookLogger.debug("No initial items; setting subscription cursor", {
|
||||
subscriptionKey,
|
||||
highestId: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [queryData, cursorKey, subscriptionKey]);
|
||||
|
|
@ -134,12 +143,20 @@ export default function useLatestWithSubscription(
|
|||
if (!subscribeToMore) return;
|
||||
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
|
||||
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
||||
console.error(
|
||||
`[${subscriptionKey}] Max retries (${maxRetries}) reached. Stopping subscription attempts.`,
|
||||
subscriptionErrorRef.current,
|
||||
);
|
||||
hookLogger.error("Max retries reached; stopping subscription attempts", {
|
||||
subscriptionKey,
|
||||
maxRetries,
|
||||
error: subscriptionErrorRef.current,
|
||||
});
|
||||
|
||||
// Report to Sentry when max retries are reached
|
||||
try {
|
||||
|
|
@ -155,17 +172,24 @@ export default function useLatestWithSubscription(
|
|||
},
|
||||
});
|
||||
} catch (sentryError) {
|
||||
console.error("Failed to report to Sentry:", sentryError);
|
||||
hookLogger.error("Failed to report max-retries to Sentry", {
|
||||
subscriptionKey,
|
||||
error: sentryError,
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for:
|
||||
// - either initial setup not done yet
|
||||
// - or a new wsClosedDate (WS reconnect)
|
||||
// - or a retry trigger
|
||||
if (initialSetupDoneRef.current && !wsClosedDate && retryTrigger === 0) {
|
||||
// - initial setup not done yet
|
||||
// - OR a new wsClosedDate (WS reconnect)
|
||||
// - OR a retry trigger
|
||||
if (
|
||||
initialSetupDoneRef.current &&
|
||||
!wsClosedDateChanged &&
|
||||
retryTrigger === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -178,6 +202,16 @@ export default function useLatestWithSubscription(
|
|||
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
|
||||
const backoffDelay =
|
||||
retryCountRef.current > 0
|
||||
|
|
@ -187,15 +221,13 @@ export default function useLatestWithSubscription(
|
|||
)
|
||||
: 0;
|
||||
|
||||
const retryMessage =
|
||||
retryCountRef.current > 0
|
||||
? ` Retry attempt ${retryCountRef.current}/${maxRetries} after ${backoffDelay}ms delay`
|
||||
: "";
|
||||
|
||||
console.log(
|
||||
`[${subscriptionKey}] Setting up subscription${retryMessage} with highestId:`,
|
||||
highestIdRef.current,
|
||||
);
|
||||
hookLogger.debug("Setting up subscription", {
|
||||
subscriptionKey,
|
||||
retryCount: retryCountRef.current,
|
||||
maxRetries,
|
||||
backoffDelay,
|
||||
highestId: highestIdRef.current,
|
||||
});
|
||||
|
||||
// Use timeout for backoff
|
||||
timeoutIdRef.current = setTimeout(() => {
|
||||
|
|
@ -222,10 +254,12 @@ export default function useLatestWithSubscription(
|
|||
maxRetries,
|
||||
);
|
||||
|
||||
console.error(
|
||||
`[${subscriptionKey}] Subscription error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||
hookLogger.warn("Subscription error", {
|
||||
subscriptionKey,
|
||||
attempt: retryCountRef.current,
|
||||
maxRetries,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
// If we haven't reached max retries, trigger a retry
|
||||
if (retryCountRef.current < maxRetries) {
|
||||
|
|
@ -270,10 +304,11 @@ export default function useLatestWithSubscription(
|
|||
}
|
||||
});
|
||||
|
||||
console.log(
|
||||
`[${subscriptionKey}] Received ${filteredNewItems.length} new items, updated highestId:`,
|
||||
highestIdRef.current,
|
||||
);
|
||||
hookLogger.debug("Received new items", {
|
||||
subscriptionKey,
|
||||
receivedCount: filteredNewItems.length,
|
||||
highestId: highestIdRef.current,
|
||||
});
|
||||
|
||||
// For latest items pattern, we prepend new items (DESC order in UI)
|
||||
return {
|
||||
|
|
@ -283,30 +318,27 @@ export default function useLatestWithSubscription(
|
|||
},
|
||||
});
|
||||
|
||||
// Cleanup on unmount or re-run
|
||||
return () => {
|
||||
console.log(`[${subscriptionKey}] Cleaning up subscription`);
|
||||
if (timeoutIdRef.current) {
|
||||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
unsubscribe();
|
||||
};
|
||||
// Save unsubscribe for cleanup on reruns/unmount
|
||||
unsubscribeRef.current = unsubscribe;
|
||||
|
||||
// Note: cleanup is handled by the effect cleanup below.
|
||||
} catch (error) {
|
||||
// Handle setup errors (like malformed queries)
|
||||
console.error(
|
||||
`[${subscriptionKey}] Error setting up subscription:`,
|
||||
hookLogger.error("Error setting up subscription", {
|
||||
subscriptionKey,
|
||||
error,
|
||||
);
|
||||
});
|
||||
subscriptionErrorRef.current = error;
|
||||
|
||||
// Increment retry counter but don't exceed maxRetries
|
||||
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
||||
|
||||
console.error(
|
||||
`[${subscriptionKey}] Subscription setup error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||
hookLogger.warn("Subscription setup error", {
|
||||
subscriptionKey,
|
||||
attempt: retryCountRef.current,
|
||||
maxRetries,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
// If we haven't reached max retries, trigger a retry
|
||||
if (retryCountRef.current < maxRetries) {
|
||||
|
|
@ -328,16 +360,14 @@ export default function useLatestWithSubscription(
|
|||
},
|
||||
});
|
||||
} catch (sentryError) {
|
||||
console.error("Failed to report to Sentry:", sentryError);
|
||||
hookLogger.error("Failed to report setup error to Sentry", {
|
||||
subscriptionKey,
|
||||
error: sentryError,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (timeoutIdRef.current) {
|
||||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
};
|
||||
// Cleanup is handled by the effect cleanup below.
|
||||
}
|
||||
}, backoffDelay);
|
||||
|
||||
|
|
@ -347,6 +377,16 @@ export default function useLatestWithSubscription(
|
|||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
|
||||
if (unsubscribeRef.current) {
|
||||
try {
|
||||
hookLogger.debug("Cleaning up subscription", { subscriptionKey });
|
||||
unsubscribeRef.current();
|
||||
} catch (_error) {
|
||||
// ignore
|
||||
}
|
||||
unsubscribeRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
skip,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,15 @@ import { useRef, useEffect, useMemo, useState } from "react";
|
|||
import { useQuery } from "@apollo/client";
|
||||
import * as Sentry from "@sentry/react-native";
|
||||
import { useNetworkState } from "~/stores";
|
||||
import { createLogger } from "~/lib/logger";
|
||||
import { UI_SCOPES } from "~/lib/logger/scopes";
|
||||
import useShallowMemo from "./useShallowMemo";
|
||||
|
||||
const hookLogger = createLogger({
|
||||
module: UI_SCOPES.HOOKS,
|
||||
feature: "useStreamQueryWithSubscription",
|
||||
});
|
||||
|
||||
// Constants for retry configuration
|
||||
const MAX_RETRIES = 5;
|
||||
const INITIAL_BACKOFF_MS = 1000; // 1 second
|
||||
|
|
@ -40,14 +47,16 @@ export default function useStreamQueryWithSubscription(
|
|||
const retryCountRef = useRef(0);
|
||||
const subscriptionErrorRef = useRef(null);
|
||||
const timeoutIdRef = useRef(null);
|
||||
const unsubscribeRef = useRef(null);
|
||||
const lastWsClosedDateRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const currentVarsHash = JSON.stringify(variables);
|
||||
if (currentVarsHash !== variableHashRef.current) {
|
||||
console.log(
|
||||
`[${subscriptionKey}] Variables changed, resetting cursor to initial value:`,
|
||||
hookLogger.debug("Variables changed; resetting cursor", {
|
||||
subscriptionKey,
|
||||
initialCursor,
|
||||
);
|
||||
});
|
||||
lastCursorRef.current = initialCursor;
|
||||
variableHashRef.current = currentVarsHash;
|
||||
initialSetupDoneRef.current = false;
|
||||
|
|
@ -99,10 +108,10 @@ export default function useStreamQueryWithSubscription(
|
|||
const newCursor = lastItem[cursorKey];
|
||||
|
||||
lastCursorRef.current = newCursor;
|
||||
console.log(
|
||||
`[${subscriptionKey}] Updated subscription cursor:`,
|
||||
newCursor,
|
||||
);
|
||||
hookLogger.debug("Updated subscription cursor", {
|
||||
subscriptionKey,
|
||||
cursor: newCursor,
|
||||
});
|
||||
}
|
||||
}, [queryData, cursorKey, subscriptionKey]);
|
||||
|
||||
|
|
@ -124,12 +133,20 @@ export default function useStreamQueryWithSubscription(
|
|||
if (skip) return; // If skipping, do nothing
|
||||
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
|
||||
if (retryCountRef.current >= maxRetries && subscriptionErrorRef.current) {
|
||||
console.error(
|
||||
`[${subscriptionKey}] Max retries (${maxRetries}) reached. Stopping subscription attempts.`,
|
||||
subscriptionErrorRef.current,
|
||||
);
|
||||
hookLogger.error("Max retries reached; stopping subscription attempts", {
|
||||
subscriptionKey,
|
||||
maxRetries,
|
||||
error: subscriptionErrorRef.current,
|
||||
});
|
||||
|
||||
// Report to Sentry when max retries are reached
|
||||
try {
|
||||
|
|
@ -145,17 +162,24 @@ export default function useStreamQueryWithSubscription(
|
|||
},
|
||||
});
|
||||
} catch (sentryError) {
|
||||
console.error("Failed to report to Sentry:", sentryError);
|
||||
hookLogger.error("Failed to report max-retries to Sentry", {
|
||||
subscriptionKey,
|
||||
error: sentryError,
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for:
|
||||
// - either initial setup not done yet
|
||||
// - or a new wsClosedDate (WS reconnect)
|
||||
// - or a retry trigger
|
||||
if (initialSetupDoneRef.current && !wsClosedDate && retryTrigger === 0) {
|
||||
// - initial setup not done yet
|
||||
// - OR a new wsClosedDate (WS reconnect)
|
||||
// - OR a retry trigger
|
||||
if (
|
||||
initialSetupDoneRef.current &&
|
||||
!wsClosedDateChanged &&
|
||||
retryTrigger === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +192,16 @@ export default function useStreamQueryWithSubscription(
|
|||
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
|
||||
const backoffDelay =
|
||||
retryCountRef.current > 0
|
||||
|
|
@ -177,15 +211,13 @@ export default function useStreamQueryWithSubscription(
|
|||
)
|
||||
: 0;
|
||||
|
||||
const retryMessage =
|
||||
retryCountRef.current > 0
|
||||
? ` Retry attempt ${retryCountRef.current}/${maxRetries} after ${backoffDelay}ms delay`
|
||||
: "";
|
||||
|
||||
console.log(
|
||||
`[${subscriptionKey}] Setting up subscription${retryMessage} with cursor:`,
|
||||
lastCursorRef.current,
|
||||
);
|
||||
hookLogger.debug("Setting up subscription", {
|
||||
subscriptionKey,
|
||||
retryCount: retryCountRef.current,
|
||||
maxRetries,
|
||||
backoffDelay,
|
||||
cursor: lastCursorRef.current,
|
||||
});
|
||||
|
||||
// Use timeout for backoff
|
||||
timeoutIdRef.current = setTimeout(() => {
|
||||
|
|
@ -212,10 +244,12 @@ export default function useStreamQueryWithSubscription(
|
|||
maxRetries,
|
||||
);
|
||||
|
||||
console.error(
|
||||
`[${subscriptionKey}] Subscription error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||
hookLogger.warn("Subscription error", {
|
||||
subscriptionKey,
|
||||
attempt: retryCountRef.current,
|
||||
maxRetries,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
// If we haven't reached max retries, trigger a retry
|
||||
if (retryCountRef.current < maxRetries) {
|
||||
|
|
@ -263,10 +297,10 @@ export default function useStreamQueryWithSubscription(
|
|||
newItemCursor > lastCursorRef.current
|
||||
) {
|
||||
lastCursorRef.current = newItemCursor;
|
||||
console.log(
|
||||
`[${subscriptionKey}] New message received with cursor:`,
|
||||
lastCursorRef.current,
|
||||
);
|
||||
hookLogger.debug("Received item; cursor advanced", {
|
||||
subscriptionKey,
|
||||
cursor: lastCursorRef.current,
|
||||
});
|
||||
}
|
||||
|
||||
const existing = itemMap.get(item[uniqKey]);
|
||||
|
|
@ -289,30 +323,27 @@ export default function useStreamQueryWithSubscription(
|
|||
},
|
||||
});
|
||||
|
||||
// Cleanup on unmount or re-run
|
||||
return () => {
|
||||
console.log(`[${subscriptionKey}] Cleaning up subscription`);
|
||||
if (timeoutIdRef.current) {
|
||||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
unsubscribe();
|
||||
};
|
||||
// Save unsubscribe for cleanup on reruns/unmount
|
||||
unsubscribeRef.current = unsubscribe;
|
||||
|
||||
// Note: cleanup is handled by the effect cleanup below.
|
||||
} catch (error) {
|
||||
// Handle setup errors (like malformed queries)
|
||||
console.error(
|
||||
`[${subscriptionKey}] Error setting up subscription:`,
|
||||
hookLogger.error("Error setting up subscription", {
|
||||
subscriptionKey,
|
||||
error,
|
||||
);
|
||||
});
|
||||
subscriptionErrorRef.current = error;
|
||||
|
||||
// Increment retry counter but don't exceed maxRetries
|
||||
retryCountRef.current = Math.min(retryCountRef.current + 1, maxRetries);
|
||||
|
||||
console.error(
|
||||
`[${subscriptionKey}] Subscription setup error (attempt ${retryCountRef.current}/${maxRetries}):`,
|
||||
hookLogger.warn("Subscription setup error", {
|
||||
subscriptionKey,
|
||||
attempt: retryCountRef.current,
|
||||
maxRetries,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
// If we haven't reached max retries, trigger a retry
|
||||
if (retryCountRef.current < maxRetries) {
|
||||
|
|
@ -334,16 +365,14 @@ export default function useStreamQueryWithSubscription(
|
|||
},
|
||||
});
|
||||
} catch (sentryError) {
|
||||
console.error("Failed to report to Sentry:", sentryError);
|
||||
hookLogger.error("Failed to report setup error to Sentry", {
|
||||
subscriptionKey,
|
||||
error: sentryError,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (timeoutIdRef.current) {
|
||||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
};
|
||||
// Cleanup is handled by the effect cleanup below.
|
||||
}
|
||||
}, backoffDelay);
|
||||
|
||||
|
|
@ -353,6 +382,16 @@ export default function useStreamQueryWithSubscription(
|
|||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = null;
|
||||
}
|
||||
|
||||
if (unsubscribeRef.current) {
|
||||
try {
|
||||
hookLogger.debug("Cleaning up subscription", { subscriptionKey });
|
||||
unsubscribeRef.current();
|
||||
} catch (_error) {
|
||||
// ignore
|
||||
}
|
||||
unsubscribeRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
skip,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue