fix(ws): stabilization try 6 + typo
This commit is contained in:
parent
ef643f77cb
commit
5dfb064c2c
5 changed files with 59 additions and 4 deletions
|
|
@ -3,6 +3,7 @@ import useStreamQueryWithSubscription from "~/hooks/useStreamQueryWithSubscripti
|
|||
import { aggregatedMessagesActions } from "~/stores";
|
||||
import { createLogger } from "~/lib/logger";
|
||||
import { FEATURE_SCOPES, NETWORK_SCOPES } from "~/lib/logger/scopes";
|
||||
import { AppState } from "react-native";
|
||||
|
||||
import {
|
||||
AGGREGATED_MESSAGES_QUERY,
|
||||
|
|
@ -17,12 +18,14 @@ const messagesLogger = createLogger({
|
|||
const AggregatedMessagesSubscription = () => {
|
||||
// Ref to track if we've already run the cleanup
|
||||
const initRunRef = useRef(false);
|
||||
const lastForegroundCatchupAtRef = useRef(0);
|
||||
|
||||
// Aggregated messages subscription
|
||||
const {
|
||||
data: messagesData,
|
||||
error: messagesError,
|
||||
loading,
|
||||
refetch,
|
||||
} = useStreamQueryWithSubscription(
|
||||
AGGREGATED_MESSAGES_QUERY,
|
||||
AGGREGATED_MESSAGES_SUBSCRIPTION,
|
||||
|
|
@ -47,6 +50,37 @@ const AggregatedMessagesSubscription = () => {
|
|||
},
|
||||
);
|
||||
|
||||
// Foreground catch-up: on mobile, WS can take time to resume after background.
|
||||
// Do a lightweight refresh shortly after the app becomes active.
|
||||
useEffect(() => {
|
||||
const sub = AppState.addEventListener("change", (next) => {
|
||||
if (next !== "active") return;
|
||||
|
||||
const now = Date.now();
|
||||
// Avoid spamming refetches if the app toggles state quickly.
|
||||
if (now - lastForegroundCatchupAtRef.current < 15_000) return;
|
||||
lastForegroundCatchupAtRef.current = now;
|
||||
|
||||
if (!refetch) return;
|
||||
try {
|
||||
messagesLogger.info(
|
||||
"Foreground catch-up: refetching aggregated messages",
|
||||
);
|
||||
Promise.resolve()
|
||||
.then(() => refetch())
|
||||
.catch((e) => {
|
||||
messagesLogger.warn("Foreground catch-up refetch failed", {
|
||||
error: e?.message,
|
||||
});
|
||||
});
|
||||
} catch (_e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
|
||||
return () => sub.remove();
|
||||
}, [refetch]);
|
||||
|
||||
// Update loading state
|
||||
useEffect(() => {
|
||||
aggregatedMessagesActions.setLoading(loading);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,12 @@ export default function useLatestWithSubscription(
|
|||
`[${subscriptionKey}] WS reconnect detected, refetching base query to prevent gaps`,
|
||||
{ wsClosedDate },
|
||||
);
|
||||
await refetch();
|
||||
// Don't block re-subscription forever if refetch is slow/stuck.
|
||||
const maxWaitMs = 8000;
|
||||
await Promise.race([
|
||||
Promise.resolve().then(() => refetch()),
|
||||
new Promise((resolve) => setTimeout(resolve, maxWaitMs)),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`[${subscriptionKey}] Refetch-on-reconnect failed (continuing with resubscribe)`,
|
||||
|
|
|
|||
|
|
@ -143,7 +143,12 @@ export default function useStreamQueryWithSubscription(
|
|||
`[${subscriptionKey}] WS reconnect detected, refetching base query to prevent gaps`,
|
||||
{ wsClosedDate },
|
||||
);
|
||||
await refetch();
|
||||
// Don't block re-subscription forever if refetch is slow/stuck.
|
||||
const maxWaitMs = 8000;
|
||||
await Promise.race([
|
||||
Promise.resolve().then(() => refetch()),
|
||||
new Promise((resolve) => setTimeout(resolve, maxWaitMs)),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`[${subscriptionKey}] Refetch-on-reconnect failed (continuing with resubscribe)`,
|
||||
|
|
@ -800,5 +805,6 @@ export default function useStreamQueryWithSubscription(
|
|||
data: queryData,
|
||||
loading,
|
||||
error,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { print } from "graphql";
|
|||
// import { createClient } from "graphql-ws";
|
||||
import { createRestartableClient } from "./graphqlWs";
|
||||
import network from "~/network";
|
||||
import { networkActions } from "~/stores";
|
||||
|
||||
export default class WebSocketLink extends ApolloLink {
|
||||
constructor(options) {
|
||||
|
|
@ -18,7 +19,16 @@ export default class WebSocketLink extends ApolloLink {
|
|||
return this.client.subscribe(
|
||||
{ ...operation, query: print(operation.query) },
|
||||
{
|
||||
next: sink.next.bind(sink),
|
||||
next: (value) => {
|
||||
// Any subscription payload means the transport is alive.
|
||||
// Touch WS heartbeat so watchdog/liveness logic doesn't falsely conclude staleness.
|
||||
try {
|
||||
networkActions.WSTouch();
|
||||
} catch (_e) {
|
||||
// ignore
|
||||
}
|
||||
sink.next(value);
|
||||
},
|
||||
complete: sink.complete.bind(sink),
|
||||
error: (err) => {
|
||||
// Don't propagate client restart events as errors
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default createAtom(({ merge, getActions }) => {
|
|||
const networkActions = getActions("network");
|
||||
|
||||
const alertActions = getActions("alert");
|
||||
const navActions = getActions("alert");
|
||||
const navActions = getActions("nav");
|
||||
const fcmActions = getActions("fcm");
|
||||
const paramsActions = getActions("params");
|
||||
const notificationsActions = getActions("notifications");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue