mirror of
https://github.com/vxcontrol/pentagi.git
synced 2026-08-25 20:46:31 +00:00
fix(flows): reconcile the cache after a websocket reconnect
The GraphQL subscriptions are delta-only: the server registers a subscriber for future events and never replays what it published while a client was disconnected (and it drops events for a disconnected subscriber outright). Nothing on the client refetched after the socket came back, so a websocket drop during an active flow — a network blip, a laptop waking, a proxy timeout — left a permanent hole in the streamed logs/messages/status until the user manually reloaded the page. Refetch the active queries on reconnect: graphql-ws hands `wasRetry` to the `connected` handler, so on a retry (not the initial connect) call `refetchObservableQueries()`, which re-runs the flow's queries and merges the full current state back into the cache. Verified live with a faithful drop (patched WebSocket, real `ws.close()` mid- flow while the agent kept producing): before the fix the messages created during the outage stayed missing after reconnect and only a reload recovered them; with the fix they reappear automatically on reconnect, no reload. (A CDP "offline" emulation does NOT reproduce this — it buffers the socket rather than closing it, so use a real close when testing.) 1006 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c2287ad90c
commit
b4b640b36b
@@ -383,6 +383,11 @@ const replaceWithIncoming = {
|
||||
};
|
||||
|
||||
const createApolloClient = () => {
|
||||
// Holds the client for the ws `connected` handler, which is defined before the
|
||||
// client exists; `lazy: true` means the socket only opens on the first
|
||||
// subscription, after `.current` is set below.
|
||||
const clientRef: { current?: ApolloClient } = {};
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
credentials: 'include',
|
||||
uri: `${window.location.origin}${GRAPHQL_ENDPOINT}`,
|
||||
@@ -393,7 +398,16 @@ const createApolloClient = () => {
|
||||
lazy: true,
|
||||
on: {
|
||||
closed: () => Log.debug('GraphQL WebSocket closed'),
|
||||
connected: () => Log.debug('GraphQL WebSocket connected'),
|
||||
connected: (_socket, _payload, wasRetry) => {
|
||||
Log.debug('GraphQL WebSocket connected');
|
||||
|
||||
// Subscriptions are delta-only — the server never replays events
|
||||
// published while we were disconnected — so on a reconnect refetch
|
||||
// active queries to reconcile the cache with the backend.
|
||||
if (wasRetry) {
|
||||
void clientRef.current?.refetchObservableQueries();
|
||||
}
|
||||
},
|
||||
connecting: () => Log.debug('GraphQL WebSocket connecting...'),
|
||||
error: (error) => {
|
||||
Log.error('GraphQL WebSocket error:', error);
|
||||
@@ -517,7 +531,7 @@ const createApolloClient = () => {
|
||||
|
||||
const link = ApolloLink.from([errorLink, subscriptionCacheLink, streamingLink, transportLink]);
|
||||
|
||||
return new ApolloClient({
|
||||
const apolloClient = new ApolloClient({
|
||||
cache,
|
||||
defaultOptions: {
|
||||
watchQuery: {
|
||||
@@ -528,6 +542,10 @@ const createApolloClient = () => {
|
||||
},
|
||||
link,
|
||||
});
|
||||
|
||||
clientRef.current = apolloClient;
|
||||
|
||||
return apolloClient;
|
||||
};
|
||||
|
||||
export const client = createApolloClient();
|
||||
|
||||
Reference in New Issue
Block a user