Reconnect idle live tape socket
This commit is contained in:
parent
5fcdb015c0
commit
820681f7b6
1 changed files with 54 additions and 1 deletions
|
|
@ -97,6 +97,15 @@ const CANDLE_INTERVALS = [
|
||||||
{ label: "1m", ms: 60000 },
|
{ label: "1m", ms: 60000 },
|
||||||
{ label: "5m", ms: 300000 }
|
{ label: "5m", ms: 300000 }
|
||||||
];
|
];
|
||||||
|
const LIVE_SESSION_IDLE_RECONNECT_MS = 12_000;
|
||||||
|
const LIVE_SESSION_IDLE_CHECK_MS = 3_000;
|
||||||
|
const LIVE_SESSION_HOT_CHANNELS = new Set<LiveSubscription["channel"]>([
|
||||||
|
"options",
|
||||||
|
"nbbo",
|
||||||
|
"equities",
|
||||||
|
"flow",
|
||||||
|
"equity-overlay"
|
||||||
|
]);
|
||||||
|
|
||||||
type CandlestickSeries = ReturnType<IChartApi["addCandlestickSeries"]>;
|
type CandlestickSeries = ReturnType<IChartApi["addCandlestickSeries"]>;
|
||||||
|
|
||||||
|
|
@ -2329,6 +2338,9 @@ const useLiveSession = (
|
||||||
const [chartOverlay, setChartOverlay] = useState<EquityPrint[]>([]);
|
const [chartOverlay, setChartOverlay] = useState<EquityPrint[]>([]);
|
||||||
const socketRef = useRef<WebSocket | null>(null);
|
const socketRef = useRef<WebSocket | null>(null);
|
||||||
const reconnectRef = useRef<number | null>(null);
|
const reconnectRef = useRef<number | null>(null);
|
||||||
|
const idleWatchdogRef = useRef<number | null>(null);
|
||||||
|
const connectedAtRef = useRef<number | null>(null);
|
||||||
|
const lastEventAtRef = useRef<number | null>(null);
|
||||||
const subscribedKeysRef = useRef<Set<string>>(new Set());
|
const subscribedKeysRef = useRef<Set<string>>(new Set());
|
||||||
const subscribedMapRef = useRef<Map<string, LiveSubscription>>(new Map());
|
const subscribedMapRef = useRef<Map<string, LiveSubscription>>(new Map());
|
||||||
const manifest = useMemo(
|
const manifest = useMemo(
|
||||||
|
|
@ -2366,6 +2378,12 @@ const useLiveSession = (
|
||||||
window.clearTimeout(reconnectRef.current);
|
window.clearTimeout(reconnectRef.current);
|
||||||
reconnectRef.current = null;
|
reconnectRef.current = null;
|
||||||
}
|
}
|
||||||
|
if (idleWatchdogRef.current !== null) {
|
||||||
|
window.clearInterval(idleWatchdogRef.current);
|
||||||
|
idleWatchdogRef.current = null;
|
||||||
|
}
|
||||||
|
connectedAtRef.current = null;
|
||||||
|
lastEventAtRef.current = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2474,6 +2492,7 @@ const useLiveSession = (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (items.length > 0) {
|
if (items.length > 0) {
|
||||||
|
lastEventAtRef.current = updateAt;
|
||||||
setLastEventByChannel((current) => ({
|
setLastEventByChannel((current) => ({
|
||||||
...current,
|
...current,
|
||||||
[subscription.channel]: updateAt
|
[subscription.channel]: updateAt
|
||||||
|
|
@ -2496,7 +2515,10 @@ const useLiveSession = (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setStatus("connected");
|
setStatus("connected");
|
||||||
setConnectedAt(Date.now());
|
const now = Date.now();
|
||||||
|
setConnectedAt(now);
|
||||||
|
connectedAtRef.current = now;
|
||||||
|
lastEventAtRef.current = null;
|
||||||
syncSubscriptions(socket);
|
syncSubscriptions(socket);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2518,6 +2540,8 @@ const useLiveSession = (
|
||||||
}
|
}
|
||||||
setStatus("disconnected");
|
setStatus("disconnected");
|
||||||
setConnectedAt(null);
|
setConnectedAt(null);
|
||||||
|
connectedAtRef.current = null;
|
||||||
|
lastEventAtRef.current = null;
|
||||||
subscribedKeysRef.current = new Set();
|
subscribedKeysRef.current = new Set();
|
||||||
subscribedMapRef.current = new Map();
|
subscribedMapRef.current = new Map();
|
||||||
reconnectRef.current = window.setTimeout(connect, 1000);
|
reconnectRef.current = window.setTimeout(connect, 1000);
|
||||||
|
|
@ -2529,14 +2553,43 @@ const useLiveSession = (
|
||||||
}
|
}
|
||||||
setStatus("disconnected");
|
setStatus("disconnected");
|
||||||
setConnectedAt(null);
|
setConnectedAt(null);
|
||||||
|
connectedAtRef.current = null;
|
||||||
|
lastEventAtRef.current = null;
|
||||||
socket.close();
|
socket.close();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
|
idleWatchdogRef.current = window.setInterval(() => {
|
||||||
|
if (!active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const socket = socketRef.current;
|
||||||
|
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const hasHotSubscription = Array.from(subscribedMapRef.current.values()).some((sub) =>
|
||||||
|
LIVE_SESSION_HOT_CHANNELS.has(sub.channel)
|
||||||
|
);
|
||||||
|
if (!hasHotSubscription) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const baseline = lastEventAtRef.current ?? connectedAtRef.current;
|
||||||
|
if (baseline === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Date.now() - baseline >= LIVE_SESSION_IDLE_RECONNECT_MS) {
|
||||||
|
console.warn("Live socket idle; reconnecting");
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
}, LIVE_SESSION_IDLE_CHECK_MS);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
active = false;
|
active = false;
|
||||||
|
if (idleWatchdogRef.current !== null) {
|
||||||
|
window.clearInterval(idleWatchdogRef.current);
|
||||||
|
idleWatchdogRef.current = null;
|
||||||
|
}
|
||||||
if (reconnectRef.current !== null) {
|
if (reconnectRef.current !== null) {
|
||||||
window.clearTimeout(reconnectRef.current);
|
window.clearTimeout(reconnectRef.current);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue