feat: add unified OA event flow
This commit is contained in:
@@ -2775,6 +2775,7 @@ async function getMicroserviceAvailabilitySummary(): Promise<Record<string, Json
|
||||
|
||||
function microserviceCacheTtlMs(serviceId: string, targetPath: string): number {
|
||||
if (targetPath === "/health") return 0;
|
||||
if (targetPath.endsWith("/stream")) return 0;
|
||||
if (serviceId === "pipeline" && targetPath === "/api/snapshot") return 6_000;
|
||||
if (serviceId === "pipeline" && targetPath.startsWith("/api/oa-event-flow/")) return 20_000;
|
||||
if (serviceId === "pipeline" && targetPath.startsWith("/api/model-quota/")) return 60_000;
|
||||
@@ -2888,22 +2889,36 @@ async function directMicroserviceResponse(
|
||||
proxyOptions: { query: string; jsonArrayLimits: Record<string, JsonValue> },
|
||||
requestHeaders: Record<string, JsonValue>,
|
||||
bodyText: string,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<Response> {
|
||||
const baseUrl = new URL(service.backend.nodeBaseUrl);
|
||||
const upstreamUrl = new URL(targetPath, baseUrl);
|
||||
upstreamUrl.search = proxyOptions.query;
|
||||
const headers = headersFromMicroserviceRequest(requestHeaders);
|
||||
const streamExpected = method === "GET" && (targetPath.endsWith("/stream") || String(headers.get("accept") || "").toLowerCase().includes("text/event-stream"));
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), Math.max(1000, service.backend.timeoutMs));
|
||||
const timer = streamExpected ? null : setTimeout(() => controller.abort(), Math.max(1000, service.backend.timeoutMs));
|
||||
try {
|
||||
const upstream = await fetch(upstreamUrl, {
|
||||
method,
|
||||
headers,
|
||||
body: method === "GET" || method === "HEAD" ? undefined : bodyText,
|
||||
signal: controller.signal,
|
||||
signal: streamExpected ? abortSignal : controller.signal,
|
||||
});
|
||||
const rawBodyText = await upstream.text();
|
||||
const upstreamContentType = upstream.headers.get("content-type") ?? "text/plain; charset=utf-8";
|
||||
if (upstreamContentType.toLowerCase().includes("text/event-stream")) {
|
||||
const responseHeaders: Record<string, string> = {
|
||||
"content-type": upstreamContentType,
|
||||
"cache-control": upstream.headers.get("cache-control") || "no-store, no-transform",
|
||||
"connection": "keep-alive",
|
||||
"x-unidesk-proxy-mode": "direct",
|
||||
"x-unidesk-response-truncated": "false",
|
||||
};
|
||||
const buffering = upstream.headers.get("x-accel-buffering");
|
||||
if (buffering !== null) responseHeaders["x-accel-buffering"] = buffering;
|
||||
return new Response(upstream.body, { status: upstream.status, headers: responseHeaders });
|
||||
}
|
||||
const rawBodyText = await upstream.text();
|
||||
const limitedBodyText = applyJsonArrayLimits(rawBodyText, upstreamContentType, proxyOptions.jsonArrayLimits);
|
||||
const bounded = boundedMicroserviceBodyText(limitedBodyText, upstreamContentType, {
|
||||
serviceId: service.id,
|
||||
@@ -2922,7 +2937,7 @@ async function directMicroserviceResponse(
|
||||
} catch (error) {
|
||||
return jsonResponse({ ok: false, error: "direct microservice proxy failed", serviceId: service.id, detail: errorToJson(error) }, 502);
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
if (timer !== null) clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2933,9 +2948,10 @@ async function fetchMicroserviceUpstreamResponse(
|
||||
proxyOptions: { query: string; jsonArrayLimits: Record<string, JsonValue> },
|
||||
requestHeaders: Record<string, JsonValue>,
|
||||
bodyText: string,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<Response> {
|
||||
if (canDirectProxyMicroservice(service)) {
|
||||
return directMicroserviceResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText);
|
||||
return directMicroserviceResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText, abortSignal);
|
||||
}
|
||||
if (!(await providerSupports(service.providerId, "microservice.http"))) {
|
||||
return jsonResponse({ ok: false, error: `provider does not declare microservice.http capability: ${service.providerId}` }, 409);
|
||||
@@ -3028,8 +3044,8 @@ async function microserviceRoute(req: Request, url: URL): Promise<Response> {
|
||||
return stale;
|
||||
}
|
||||
}
|
||||
const response = await fetchMicroserviceUpstreamResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText);
|
||||
if (method === "GET" || method === "HEAD") rememberMicroserviceCache(cacheKey, cacheTtlMs, await cacheableResponseSnapshot(response));
|
||||
const response = await fetchMicroserviceUpstreamResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText, req.signal);
|
||||
if ((method === "GET" || method === "HEAD") && cacheTtlMs > 0) rememberMicroserviceCache(cacheKey, cacheTtlMs, await cacheableResponseSnapshot(response));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user