mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
Fix codex
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// Stream handler with disconnect detection - shared for all providers
|
||||
import { STREAM_STALL_TIMEOUT_MS } from "../config/runtimeConfig.js";
|
||||
import { dbg, isDebugEnabled } from "./debugLog.js";
|
||||
|
||||
// Get HH:MM:SS timestamp
|
||||
function getTimeString() {
|
||||
@@ -38,6 +39,7 @@ export function createStreamController({ onDisconnect, onError, log, provider, m
|
||||
disconnected = true;
|
||||
|
||||
logStream(`disconnect: ${reason}`);
|
||||
dbg("CTRL", `${provider}/${model} | disconnect=${reason} | dur=${Date.now() - startTime}ms`);
|
||||
|
||||
// Delay abort to allow cleanup
|
||||
abortTimeout = setTimeout(() => {
|
||||
@@ -117,8 +119,23 @@ export function createDisconnectAwareStream(transformStream, streamController) {
|
||||
streamController.handleError(error);
|
||||
reader.cancel().catch(() => {});
|
||||
writer.abort().catch(() => {});
|
||||
|
||||
if (!wasConnected || error.name === "AbortError" || error.message?.includes("aborted")) {
|
||||
|
||||
// Treat network resets / socket hang up / abort as graceful close
|
||||
const msg = error?.message || "";
|
||||
const code = error?.code || error?.cause?.code || "";
|
||||
const isNetworkClose =
|
||||
error.name === "AbortError" ||
|
||||
msg.includes("aborted") ||
|
||||
msg.includes("socket hang up") ||
|
||||
msg.includes("ECONNRESET") ||
|
||||
msg.includes("ETIMEDOUT") ||
|
||||
msg.includes("EPIPE") ||
|
||||
code === "ECONNRESET" ||
|
||||
code === "ETIMEDOUT" ||
|
||||
code === "EPIPE" ||
|
||||
code === "UND_ERR_SOCKET";
|
||||
|
||||
if (!wasConnected || isNetworkClose) {
|
||||
try {
|
||||
controller.close();
|
||||
} catch (e) {
|
||||
@@ -158,6 +175,11 @@ export function createDisconnectAwareStream(transformStream, streamController) {
|
||||
*/
|
||||
export function pipeWithDisconnect(providerResponse, transformStream, streamController) {
|
||||
let stallTimer = null;
|
||||
let chunkCount = 0;
|
||||
let totalBytes = 0;
|
||||
let lastChunkAt = Date.now();
|
||||
const t0 = Date.now();
|
||||
const tag = "STREAM";
|
||||
const clearStall = () => {
|
||||
if (stallTimer) { clearTimeout(stallTimer); stallTimer = null; }
|
||||
};
|
||||
@@ -165,6 +187,7 @@ export function pipeWithDisconnect(providerResponse, transformStream, streamCont
|
||||
clearStall();
|
||||
stallTimer = setTimeout(() => {
|
||||
stallTimer = null;
|
||||
dbg(tag, `STALL TIMEOUT ${STREAM_STALL_TIMEOUT_MS}ms | chunks=${chunkCount} | bytes=${totalBytes} | sinceLast=${Date.now() - lastChunkAt}ms`);
|
||||
streamController.handleError?.(new Error("stream stall timeout"));
|
||||
streamController.abort?.();
|
||||
}, STREAM_STALL_TIMEOUT_MS);
|
||||
@@ -177,20 +200,30 @@ export function pipeWithDisconnect(providerResponse, transformStream, streamCont
|
||||
signal: streamController.signal,
|
||||
startTime: streamController.startTime,
|
||||
isConnected: () => streamController.isConnected(),
|
||||
handleComplete: () => { clearStall(); streamController.handleComplete(); },
|
||||
handleError: (e) => { clearStall(); streamController.handleError(e); },
|
||||
handleDisconnect: (r) => { clearStall(); streamController.handleDisconnect(r); },
|
||||
handleComplete: () => { dbg(tag, `complete | chunks=${chunkCount} | bytes=${totalBytes} | dur=${Date.now() - t0}ms`); clearStall(); streamController.handleComplete(); },
|
||||
handleError: (e) => { dbg(tag, `error: ${e?.message} | chunks=${chunkCount} | bytes=${totalBytes} | dur=${Date.now() - t0}ms`); clearStall(); streamController.handleError(e); },
|
||||
handleDisconnect: (r) => { dbg(tag, `disconnect: ${r} | chunks=${chunkCount} | bytes=${totalBytes} | dur=${Date.now() - t0}ms`); clearStall(); streamController.handleDisconnect(r); },
|
||||
abort: () => { clearStall(); streamController.abort(); }
|
||||
};
|
||||
|
||||
armStall();
|
||||
dbg(tag, `pipe start | stallTimeout=${STREAM_STALL_TIMEOUT_MS}ms`);
|
||||
|
||||
const upstreamTap = new TransformStream({
|
||||
transform(chunk, controller) {
|
||||
chunkCount++;
|
||||
const sz = chunk?.byteLength || chunk?.length || 0;
|
||||
totalBytes += sz;
|
||||
const now = Date.now();
|
||||
const gap = now - lastChunkAt;
|
||||
lastChunkAt = now;
|
||||
if (isDebugEnabled && (chunkCount <= 5 || chunkCount % 20 === 0 || gap > 5000)) {
|
||||
dbg(tag, `chunk #${chunkCount} | size=${sz}B | gap=${gap}ms | total=${totalBytes}B`);
|
||||
}
|
||||
armStall();
|
||||
controller.enqueue(chunk);
|
||||
},
|
||||
flush() { clearStall(); }
|
||||
flush() { dbg(tag, `upstream EOF | chunks=${chunkCount} | bytes=${totalBytes} | dur=${Date.now() - t0}ms`); clearStall(); }
|
||||
});
|
||||
|
||||
const transformedBody = providerResponse.body
|
||||
|
||||
Reference in New Issue
Block a user