Skip to content

Commit

Permalink
Reconnecting websockets (All-Hands-AI#4954)
Browse files Browse the repository at this point in the history
  • Loading branch information
tofarr authored Nov 13, 2024
1 parent 207df9d commit 87c0217
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions frontend/src/context/ws-client-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import ActionType from "#/types/ActionType";
import EventLogger from "#/utils/event-logger";
import AgentState from "#/types/AgentState";

const RECONNECT_RETRIES = 5;

export enum WsClientProviderStatus {
STOPPED,
OPENING,
Expand Down Expand Up @@ -46,6 +48,7 @@ export function WsClientProvider({
const closeRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const [status, setStatus] = React.useState(WsClientProviderStatus.STOPPED);
const [events, setEvents] = React.useState<Record<string, unknown>[]>([]);
const [retryCount, setRetryCount] = React.useState(RECONNECT_RETRIES);

function send(event: Record<string, unknown>) {
if (!wsRef.current) {
Expand All @@ -56,6 +59,7 @@ export function WsClientProvider({
}

function handleOpen() {
setRetryCount(RECONNECT_RETRIES);
setStatus(WsClientProviderStatus.OPENING);
const initEvent = {
action: ActionType.INIT,
Expand All @@ -79,8 +83,14 @@ export function WsClientProvider({
}

function handleClose() {
setStatus(WsClientProviderStatus.STOPPED);
setEvents([]);
if (retryCount) {
setTimeout(() => {
setRetryCount(retryCount - 1);
}, 1000);
} else {
setStatus(WsClientProviderStatus.STOPPED);
setEvents([]);
}
wsRef.current = null;
}

Expand All @@ -95,7 +105,7 @@ export function WsClientProvider({
let ws = wsRef.current;

// If disabled close any existing websockets...
if (!enabled) {
if (!enabled || !retryCount) {
if (ws) {
ws.close();
}
Expand All @@ -116,7 +126,11 @@ export function WsClientProvider({
const baseUrl =
import.meta.env.VITE_BACKEND_BASE_URL || window?.location.host;
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
ws = new WebSocket(`${protocol}//${baseUrl}/ws`, [
let wsUrl = `${protocol}//${baseUrl}/ws`;
if (events.length) {
wsUrl += `?latest_event_id=${events[events.length - 1].id}`;
}
ws = new WebSocket(wsUrl, [
"openhands",
token || "NO_JWT",
ghToken || "NO_GITHUB",
Expand All @@ -136,7 +150,7 @@ export function WsClientProvider({
ws.removeEventListener("error", handleError);
ws.removeEventListener("close", handleClose);
};
}, [enabled, token, ghToken]);
}, [enabled, token, ghToken, retryCount]);

// Strict mode mounts and unmounts each component twice, so we have to wait in the destructor
// before actually closing the socket and cancel the operation if the component gets remounted.
Expand All @@ -148,7 +162,11 @@ export function WsClientProvider({

return () => {
closeRef.current = setTimeout(() => {
wsRef.current?.close();
const ws = wsRef.current;
if (ws) {
ws.removeEventListener("close", handleClose);
ws.close();
}
}, 100);
};
}, []);
Expand Down

0 comments on commit 87c0217

Please sign in to comment.