fix: streaming reliability, timeout, memory leaks, and retry improvements
- Fix streaming timeout: use AbortController for connection-only timeout instead of AbortSignal.timeout() that kills active SSE streams - Fix fetchViaCurl: stream body via ReadableStream instead of buffering entire response in memory - Fix JWT/aichat race condition: add Promise dedup to prevent concurrent bootstrap calls (10 requests = 1 bootstrap, not 10) - Fix ACTIVE_READERS memory leak: auto-remove readers on stream completion - Fix WebSocket backpressure: log warning when client buffer exceeds 1MB - Add SSE heartbeat/keepalive: send ': keepalive' every 15s to prevent LB/proxy timeout during AI thinking - Fix SSELineBuffer: graceful overflow handling (warn + discard instead of throwing error that crashes stream) - Fix transformStream tight loop: yield to event loop after each chunk to prevent starvation - Fix fetchViaCurl process cleanup: use SIGKILL + proper timeout cleanup - Add retry on 502/504: retry transient server errors before returning to caller (both fetchWithRetry and fetchWithSessionRetry)
This commit is contained in:
@@ -18,6 +18,7 @@ import * as os from "node:os";
|
||||
|
||||
let cachedJwt: string | null = null;
|
||||
let jwtExpiry = 0; // epoch ms
|
||||
let pendingRefresh: Promise<string> | null = null; // dedup concurrent refreshes
|
||||
|
||||
const MIMO_BOOTSTRAP_URL = "https://api.xiaomimimo.com/api/free-ai/bootstrap";
|
||||
const EXPIRY_BUFFER_MS = 300_000; // 5 minutes
|
||||
@@ -112,7 +113,13 @@ export async function getJwt(): Promise<string> {
|
||||
if (cachedJwt && jwtExpiry > now + EXPIRY_BUFFER_MS) {
|
||||
return cachedJwt;
|
||||
}
|
||||
return bootstrapJwt();
|
||||
// Dedup concurrent refresh — all callers share the same Promise
|
||||
if (!pendingRefresh) {
|
||||
pendingRefresh = bootstrapJwt().finally(() => {
|
||||
pendingRefresh = null;
|
||||
});
|
||||
}
|
||||
return pendingRefresh;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,4 +131,5 @@ export async function getJwt(): Promise<string> {
|
||||
export function invalidateJwt(): void {
|
||||
cachedJwt = null;
|
||||
jwtExpiry = 0;
|
||||
pendingRefresh = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user