fix(worldlabs): increase world 3d api request timeouts
This commit is contained in:
parent
74adb68d16
commit
6b90b25d5c
@ -98,6 +98,9 @@ WORLDLABS_API_KEY=
|
||||
WORLDLABS_BASE_URL=
|
||||
WORLDLABS_IMPORT_TOKEN=
|
||||
WORLDLABS_KEY_POOL_IMPORT_TOKEN=
|
||||
WORLDLABS_API_TIMEOUT_MS=180000
|
||||
WORLDLABS_TASK_CREATE_TIMEOUT_MS=180000
|
||||
WORLDLABS_TASK_STATUS_TIMEOUT_MS=180000
|
||||
KITTYCAD_API_TOKEN=
|
||||
KITTYCAD_API_KEY=
|
||||
KITTYCAD_BASE_URL=https://api.zoo.dev
|
||||
|
||||
@ -16,9 +16,18 @@ import type {
|
||||
} from "@/lib/worldlabs/types";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 120;
|
||||
export const maxDuration = 180;
|
||||
|
||||
const logger = createLogger("world-labs-task-status");
|
||||
const WORLDLABS_TASK_STATUS_TIMEOUT_MS =
|
||||
Number.parseInt(String(process.env.WORLDLABS_TASK_STATUS_TIMEOUT_MS || "").trim(), 10) ||
|
||||
180_000;
|
||||
|
||||
function resolveWorldLabsStatusTimeoutMs() {
|
||||
if (!Number.isFinite(WORLDLABS_TASK_STATUS_TIMEOUT_MS)) return 180_000;
|
||||
if (WORLDLABS_TASK_STATUS_TIMEOUT_MS <= 0) return 180_000;
|
||||
return WORLDLABS_TASK_STATUS_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
type ArchiveCacheItem = {
|
||||
sourceUrl: string;
|
||||
@ -446,6 +455,7 @@ export async function GET(request: Request, { params }: RouteParams) {
|
||||
const operation = await worldLabsRequest<WorldLabsOperation>(config, {
|
||||
method: "GET",
|
||||
path: `/marble/v1/operations/${encodeURIComponent(normalizedTaskId)}`,
|
||||
timeoutMs: resolveWorldLabsStatusTimeoutMs(),
|
||||
});
|
||||
|
||||
if (!operation.done) {
|
||||
@ -505,6 +515,7 @@ export async function GET(request: Request, { params }: RouteParams) {
|
||||
const detailedWorld = await worldLabsRequest<WorldLabsWorld>(config, {
|
||||
method: "GET",
|
||||
path: `/marble/v1/worlds/${encodeURIComponent(worldId)}`,
|
||||
timeoutMs: resolveWorldLabsStatusTimeoutMs(),
|
||||
});
|
||||
world = world
|
||||
? {
|
||||
|
||||
@ -21,9 +21,18 @@ import {
|
||||
import type { WorldLabsModel, WorldLabsOperation } from "@/lib/worldlabs/types";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 60;
|
||||
export const maxDuration = 180;
|
||||
|
||||
const logger = createLogger("world-labs-task-create");
|
||||
const WORLDLABS_TASK_CREATE_TIMEOUT_MS =
|
||||
Number.parseInt(String(process.env.WORLDLABS_TASK_CREATE_TIMEOUT_MS || "").trim(), 10) ||
|
||||
180_000;
|
||||
|
||||
function resolveWorldLabsCreateTimeoutMs() {
|
||||
if (!Number.isFinite(WORLDLABS_TASK_CREATE_TIMEOUT_MS)) return 180_000;
|
||||
if (WORLDLABS_TASK_CREATE_TIMEOUT_MS <= 0) return 180_000;
|
||||
return WORLDLABS_TASK_CREATE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
type WorldTaskMode = "text" | "image" | "multi-image" | "video";
|
||||
|
||||
@ -236,6 +245,7 @@ export async function POST(request: Request) {
|
||||
result = await worldLabsRequest<WorldLabsOperation>(candidate, {
|
||||
method: "POST",
|
||||
path: "/marble/v1/worlds:generate",
|
||||
timeoutMs: resolveWorldLabsCreateTimeoutMs(),
|
||||
json: {
|
||||
display_name: displayName,
|
||||
model: resolvedWorldModel || "marble-1.1",
|
||||
|
||||
@ -7,9 +7,43 @@ type WorldLabsRequestOptions = {
|
||||
path: string;
|
||||
json?: Record<string, unknown>;
|
||||
headers?: Record<string, string>;
|
||||
timeoutMs?: number;
|
||||
};
|
||||
|
||||
const DEFAULT_WORLDLABS_BASE_URL = "https://api.worldlabs.ai";
|
||||
const DEFAULT_WORLDLABS_REQUEST_TIMEOUT_MS = 180_000;
|
||||
|
||||
function toIntMs(value: string | undefined) {
|
||||
const parsed = Number.parseInt(String(value || "").trim(), 10);
|
||||
if (!Number.isFinite(parsed) || parsed <= 0) {
|
||||
return null;
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function getDefaultWorldLabsTimeoutMs() {
|
||||
return toIntMs(process.env.WORLDLABS_API_TIMEOUT_MS) || DEFAULT_WORLDLABS_REQUEST_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
function createRequestSignal(timeoutMs: number) {
|
||||
const timeoutSignal = (globalThis as Record<string, unknown>).AbortSignal;
|
||||
if (timeoutSignal && typeof (timeoutSignal as typeof AbortSignal).timeout === "function") {
|
||||
return {
|
||||
signal: (timeoutSignal as typeof AbortSignal).timeout(timeoutMs),
|
||||
cancel: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => {
|
||||
controller.abort(`World Labs 请求超时 (${timeoutMs}ms)`);
|
||||
}, timeoutMs);
|
||||
|
||||
return {
|
||||
signal: controller.signal,
|
||||
cancel: () => clearTimeout(timer),
|
||||
};
|
||||
}
|
||||
|
||||
export class WorldLabsApiError extends Error {
|
||||
httpStatus: number;
|
||||
@ -97,21 +131,37 @@ export async function worldLabsRequest<T = unknown>(
|
||||
body = JSON.stringify(options.json);
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: options.method || "GET",
|
||||
headers,
|
||||
body,
|
||||
cache: "no-store",
|
||||
});
|
||||
const parsed = await parseResponseBody(response);
|
||||
const timeoutMs = options.timeoutMs || getDefaultWorldLabsTimeoutMs();
|
||||
const { signal, cancel } = createRequestSignal(timeoutMs);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new WorldLabsApiError({
|
||||
message: extractErrorMessage(parsed, `World Labs 请求失败(HTTP ${response.status})`),
|
||||
httpStatus: response.status,
|
||||
payload: parsed,
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: options.method || "GET",
|
||||
headers,
|
||||
body,
|
||||
cache: "no-store",
|
||||
signal,
|
||||
});
|
||||
}
|
||||
const parsed = await parseResponseBody(response);
|
||||
|
||||
return parsed as T;
|
||||
if (!response.ok) {
|
||||
throw new WorldLabsApiError({
|
||||
message: extractErrorMessage(parsed, `World Labs 请求失败(HTTP ${response.status})`),
|
||||
httpStatus: response.status,
|
||||
payload: parsed,
|
||||
});
|
||||
}
|
||||
|
||||
return parsed as T;
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.name === "AbortError") {
|
||||
throw new WorldLabsApiError({
|
||||
message: `World Labs 请求超时(${timeoutMs}ms)`,
|
||||
httpStatus: 504,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user