fix: network reset navigation drift
This commit is contained in:
parent
47928ce9f2
commit
8a25474770
5 changed files with 73 additions and 16 deletions
|
|
@ -128,7 +128,7 @@ export default function useLatestWithSubscription(
|
|||
|
||||
// Some devices keep the WS transport "connected" after a lock/unlock, but the
|
||||
// per-operation subscription stops delivering. Trigger a controlled resubscribe.
|
||||
const FOREGROUND_KICK_MIN_INACTIVE_MS = 3_000;
|
||||
const FOREGROUND_KICK_MIN_INACTIVE_MS = 30_000;
|
||||
const FOREGROUND_KICK_MIN_INTERVAL_MS = 15_000;
|
||||
|
||||
if (
|
||||
|
|
@ -239,6 +239,15 @@ export default function useLatestWithSubscription(
|
|||
if (age < livenessStaleMs) return;
|
||||
|
||||
const now = Date.now();
|
||||
const becameInactiveAt = lastBecameInactiveAtRef.current;
|
||||
const inactiveWindowMs = becameInactiveAt ? now - becameInactiveAt : null;
|
||||
if (
|
||||
typeof inactiveWindowMs === "number" &&
|
||||
inactiveWindowMs < livenessStaleMs + 15_000
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (now - lastLivenessKickAtRef.current < livenessStaleMs) return;
|
||||
lastLivenessKickAtRef.current = now;
|
||||
|
||||
|
|
@ -276,7 +285,7 @@ export default function useLatestWithSubscription(
|
|||
|
||||
// Escalation policy for repeated consecutive stale kicks.
|
||||
if (
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_RELOAD &&
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_RELOAD + 2 &&
|
||||
now - lastReloadAtRef.current >= MIN_ESCALATION_INTERVAL_MS
|
||||
) {
|
||||
const lastRecovery = wsLastRecoveryDateRef.current
|
||||
|
|
@ -310,7 +319,7 @@ export default function useLatestWithSubscription(
|
|||
// ignore
|
||||
}
|
||||
|
||||
networkActions.triggerReload();
|
||||
networkActions.triggerReload("transport");
|
||||
} else if (
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_WS_RESTART &&
|
||||
now - lastWsRestartAtRef.current >= MIN_ESCALATION_INTERVAL_MS
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ export default function useStreamQueryWithSubscription(
|
|||
|
||||
// Some devices keep the WS transport "connected" after a lock/unlock, but the
|
||||
// per-operation subscription stops delivering. Trigger a controlled resubscribe.
|
||||
const FOREGROUND_KICK_MIN_INACTIVE_MS = 3_000;
|
||||
const FOREGROUND_KICK_MIN_INACTIVE_MS = 30_000;
|
||||
const FOREGROUND_KICK_MIN_INTERVAL_MS = 15_000;
|
||||
|
||||
if (
|
||||
|
|
@ -281,6 +281,15 @@ export default function useStreamQueryWithSubscription(
|
|||
});
|
||||
}
|
||||
// Avoid spamming resubscribe triggers.
|
||||
const becameInactiveAt = lastBecameInactiveAtRef.current;
|
||||
const inactiveWindowMs = becameInactiveAt ? now - becameInactiveAt : null;
|
||||
if (
|
||||
typeof inactiveWindowMs === "number" &&
|
||||
inactiveWindowMs < livenessStaleMs + 15_000
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (now - lastLivenessKickAtRef.current < livenessStaleMs) return;
|
||||
lastLivenessKickAtRef.current = now;
|
||||
|
||||
|
|
@ -318,7 +327,7 @@ export default function useStreamQueryWithSubscription(
|
|||
|
||||
// Escalation policy for repeated consecutive stale kicks.
|
||||
if (
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_RELOAD &&
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_RELOAD + 2 &&
|
||||
now - lastReloadAtRef.current >= MIN_ESCALATION_INTERVAL_MS
|
||||
) {
|
||||
const lastRecovery = wsLastRecoveryDateRef.current
|
||||
|
|
@ -352,7 +361,7 @@ export default function useStreamQueryWithSubscription(
|
|||
// ignore
|
||||
}
|
||||
|
||||
networkActions.triggerReload();
|
||||
networkActions.triggerReload("transport");
|
||||
} else if (
|
||||
consecutiveStaleKicksRef.current >= STALE_KICKS_BEFORE_WS_RESTART &&
|
||||
now - lastWsRestartAtRef.current >= MIN_ESCALATION_INTERVAL_MS
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import getRetryMaxAttempts from "./getRetryMaxAttemps";
|
|||
|
||||
import { createLogger } from "~/lib/logger";
|
||||
import { NETWORK_SCOPES } from "~/lib/logger/scopes";
|
||||
import createCache from "./cache";
|
||||
|
||||
const { useNetworkState, networkActions } = store;
|
||||
|
||||
|
|
@ -28,11 +29,15 @@ const networkProvidersLogger = createLogger({
|
|||
feature: "NetworkProviders",
|
||||
});
|
||||
|
||||
const sharedApolloCache = createCache();
|
||||
|
||||
const initializeNewApolloClient = (reload) => {
|
||||
if (reload) {
|
||||
const { apolloClient } = network;
|
||||
apolloClient.stop();
|
||||
apolloClient.clearStore();
|
||||
if (apolloClient.cache !== sharedApolloCache) {
|
||||
apolloClient.clearStore();
|
||||
}
|
||||
}
|
||||
|
||||
network.apolloClient = createApolloClient({
|
||||
|
|
@ -40,6 +45,7 @@ const initializeNewApolloClient = (reload) => {
|
|||
GRAPHQL_URL: env.GRAPHQL_URL,
|
||||
GRAPHQL_WS_URL: env.GRAPHQL_WS_URL,
|
||||
getRetryMaxAttempts,
|
||||
cache: sharedApolloCache,
|
||||
});
|
||||
};
|
||||
initializeNewApolloClient();
|
||||
|
|
@ -51,34 +57,60 @@ network.oaFilesKy = oaFilesKy;
|
|||
|
||||
export default function NetworkProviders({ children }) {
|
||||
const [key, setKey] = useState(0);
|
||||
const [transportClient, setTransportClient] = useState(() => network.apolloClient);
|
||||
|
||||
const networkState = useNetworkState(["initialized", "triggerReload"]);
|
||||
const networkState = useNetworkState([
|
||||
"initialized",
|
||||
"triggerReload",
|
||||
"reloadKind",
|
||||
"transportGeneration",
|
||||
]);
|
||||
useEffect(() => {
|
||||
if (networkState.triggerReload) {
|
||||
networkProvidersLogger.debug("Network triggerReload received", {
|
||||
reloadKind: networkState.reloadKind,
|
||||
reloadId: store.getAuthState()?.reloadId,
|
||||
hasUserToken: !!store.getAuthState()?.userToken,
|
||||
});
|
||||
|
||||
const isFullReload = networkState.reloadKind !== "transport";
|
||||
initializeNewApolloClient(true);
|
||||
setKey((prevKey) => prevKey + 1);
|
||||
|
||||
if (isFullReload) {
|
||||
setTransportClient(network.apolloClient);
|
||||
setKey((prevKey) => prevKey + 1);
|
||||
} else {
|
||||
setTransportClient(network.apolloClient);
|
||||
networkProvidersLogger.debug("Network transport recovered in place", {
|
||||
reloadId: store.getAuthState()?.reloadId,
|
||||
hasUserToken: !!store.getAuthState()?.userToken,
|
||||
transportGeneration: networkState.transportGeneration,
|
||||
});
|
||||
networkActions.onReload();
|
||||
}
|
||||
}
|
||||
}, [networkState.triggerReload]);
|
||||
}, [
|
||||
networkState.triggerReload,
|
||||
networkState.reloadKind,
|
||||
networkState.transportGeneration,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (key > 0) {
|
||||
networkProvidersLogger.debug("Network reloaded", {
|
||||
reloadKind: networkState.reloadKind,
|
||||
reloadId: store.getAuthState()?.reloadId,
|
||||
hasUserToken: !!store.getAuthState()?.userToken,
|
||||
});
|
||||
networkActions.onReload();
|
||||
}
|
||||
}, [key]);
|
||||
}, [key, networkState.reloadKind]);
|
||||
|
||||
if (!networkState.initialized) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
const providers = [[ApolloProvider, { client: network.apolloClient }]];
|
||||
const providers = [[ApolloProvider, { client: transportClient }]];
|
||||
|
||||
return (
|
||||
<ComposeComponents key={key} components={providers}>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ if (__DEV__ || process.env.NODE_ENV !== "production") {
|
|||
}
|
||||
|
||||
export default function createApolloClient(options) {
|
||||
const cache = options.cache || createCache();
|
||||
const errorLink = createErrorLink(options);
|
||||
const authLink = createAuthLink(options);
|
||||
const cancelLink = createCancelLink();
|
||||
|
|
@ -50,8 +51,6 @@ export default function createApolloClient(options) {
|
|||
httpLink: httpChain,
|
||||
});
|
||||
|
||||
const cache = createCache();
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
cache,
|
||||
// connectToDevTools: true, // Enable dev tools for better debugging
|
||||
|
|
|
|||
|
|
@ -9,20 +9,28 @@ export default createAtom(({ merge, get }) => {
|
|||
wsLastHeartbeatDate: null,
|
||||
wsLastRecoveryDate: null,
|
||||
triggerReload: false,
|
||||
reloadKind: null,
|
||||
initialized: true,
|
||||
hasInternetConnection: true,
|
||||
transportGeneration: 0,
|
||||
},
|
||||
actions: {
|
||||
triggerReload: () => {
|
||||
triggerReload: (reloadKind = "full") => {
|
||||
merge({
|
||||
initialized: false,
|
||||
triggerReload: true,
|
||||
reloadKind,
|
||||
initialized: reloadKind === "transport" ? true : false,
|
||||
transportGeneration:
|
||||
reloadKind === "transport"
|
||||
? get("transportGeneration") + 1
|
||||
: get("transportGeneration"),
|
||||
});
|
||||
},
|
||||
onReload: () => {
|
||||
merge({
|
||||
initialized: true,
|
||||
triggerReload: false,
|
||||
reloadKind: null,
|
||||
});
|
||||
},
|
||||
WSConnected: () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue