fix(scripts): clamp openwebui probe timers

This commit is contained in:
Vincent Koc
2026-06-22 03:35:30 +02:00
parent 8e24695a8d
commit e913e0739d
2 changed files with 35 additions and 13 deletions
+23 -7
View File
@@ -7,14 +7,15 @@ const email = process.env.OPENWEBUI_ADMIN_EMAIL ?? "";
const password = process.env.OPENWEBUI_ADMIN_PASSWORD ?? "";
const expectedNonce = process.env.OPENWEBUI_EXPECTED_NONCE ?? "";
const prompt = process.env.OPENWEBUI_PROMPT ?? "";
const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
const modelAttempts = readPositiveInt("OPENWEBUI_MODEL_ATTEMPTS", 72);
const modelRetryMs = readNonNegativeInt("OPENWEBUI_MODEL_RETRY_MS", 5000);
const fetchTimeoutMs = readPositiveInt("OPENWEBUI_FETCH_TIMEOUT_MS", 720000);
const controlTimeoutMs = readPositiveInt(
const modelRetryMs = readNonNegativeTimerMs("OPENWEBUI_MODEL_RETRY_MS", 5000);
const fetchTimeoutMs = readPositiveTimerMs("OPENWEBUI_FETCH_TIMEOUT_MS", 720000);
const controlTimeoutMs = readPositiveTimerMs(
"OPENWEBUI_CONTROL_TIMEOUT_MS",
Math.min(fetchTimeoutMs, 30000),
);
const chatTimeoutMs = readPositiveInt("OPENWEBUI_CHAT_TIMEOUT_MS", fetchTimeoutMs);
const chatTimeoutMs = readPositiveTimerMs("OPENWEBUI_CHAT_TIMEOUT_MS", fetchTimeoutMs);
const responseBodyMaxBytes = readPositiveInt("OPENWEBUI_RESPONSE_BODY_MAX_BYTES", 1024 * 1024);
const smokeMode =
process.env.OPENWEBUI_SMOKE_MODE ?? process.env.OPENCLAW_OPENWEBUI_SMOKE_MODE ?? "chat";
@@ -65,6 +66,20 @@ function readNonNegativeInt(name, fallback) {
return parsed;
}
function clampTimerTimeoutMs(valueMs, minMs = 1) {
const min = Math.max(0, Math.floor(minMs));
const value = Number.isFinite(valueMs) ? valueMs : min;
return Math.min(Math.max(Math.floor(value), min), MAX_TIMER_TIMEOUT_MS);
}
function readPositiveTimerMs(name, fallback) {
return clampTimerTimeoutMs(readPositiveInt(name, fallback));
}
function readNonNegativeTimerMs(name, fallback) {
return clampTimerTimeoutMs(readNonNegativeInt(name, fallback), 0);
}
function createTimeoutError(label, timeoutMs) {
const error = new Error(`${label} timed out after ${timeoutMs}ms`);
error.code = "ETIMEDOUT";
@@ -72,14 +87,15 @@ function createTimeoutError(label, timeoutMs) {
}
async function withRequestTimeout(label, timeoutMs, run) {
const resolvedTimeoutMs = clampTimerTimeoutMs(timeoutMs);
const controller = new AbortController();
const timeoutError = createTimeoutError(label, timeoutMs);
const timeoutError = createTimeoutError(label, resolvedTimeoutMs);
let timer;
const timeoutPromise = new Promise((_, reject) => {
timer = setTimeout(() => {
controller.abort(timeoutError);
reject(timeoutError);
}, timeoutMs);
}, resolvedTimeoutMs);
timer.unref?.();
});
try {
@@ -138,7 +154,7 @@ function buildAuthHeaders(token, cookie) {
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
setTimeout(resolve, clampTimerTimeoutMs(ms, 0));
});
}
@@ -4,6 +4,7 @@ import { readFileSync } from "node:fs";
import { createServer, type IncomingMessage, type Server as HttpServer } from "node:http";
import { createServer as createTcpServer, type Server as TcpServer, type Socket } from "node:net";
import path from "node:path";
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
import { describe, expect, it } from "vitest";
import { createBoundedChildOutput } from "../../../helpers/bounded-child-output.js";
@@ -361,11 +362,13 @@ describe("scripts/e2e/openwebui-probe.mjs", () => {
it("passes in models mode when Open WebUI exposes the OpenClaw model", async () => {
const server = createServer((request, response) => {
if (request.url === "/api/v1/auths/signin") {
response.writeHead(200, {
"content-type": "application/json",
"set-cookie": "openwebui-session=test; Path=/",
});
response.end(JSON.stringify({ token: "test-token" }));
setTimeout(() => {
response.writeHead(200, {
"content-type": "application/json",
"set-cookie": "openwebui-session=test; Path=/",
});
response.end(JSON.stringify({ token: "test-token" }));
}, 25);
return;
}
if (request.url === "/api/models") {
@@ -379,7 +382,10 @@ describe("scripts/e2e/openwebui-probe.mjs", () => {
});
const baseUrl = await listen(server);
try {
const result = await runProbe(baseUrl);
const result = await runProbe(baseUrl, {
OPENWEBUI_CONTROL_TIMEOUT_MS: String(MAX_TIMER_TIMEOUT_MS + 1),
OPENWEBUI_FETCH_TIMEOUT_MS: String(MAX_TIMER_TIMEOUT_MS + 1),
});
expect(result.status).toBe(0);
expect(JSON.parse(result.stdout)).toMatchObject({