fix: deduplicate workbench requests and remove unused map paths
This commit is contained in:
@@ -220,24 +220,16 @@ export type AgentApiClientOptions = {
|
||||
getProjectId?: () => Promise<string | undefined>;
|
||||
};
|
||||
|
||||
const AGENT_API_BASE_URLS = [env.TJWATER_AGENT_URL.replace(/\/$/, "")];
|
||||
|
||||
const API_PATH = "/api/v1";
|
||||
|
||||
export function createAgentApiClient(
|
||||
baseUrls: string | string[] = AGENT_API_BASE_URLS,
|
||||
baseUrl: string = env.TJWATER_AGENT_URL,
|
||||
options: AgentApiClientOptions = {}
|
||||
): AgentApiClient {
|
||||
const candidates = (Array.isArray(baseUrls) ? baseUrls : [baseUrls]).map((item) => item.replace(/\/$/, ""));
|
||||
let activeBaseUrl = candidates[0] ?? "";
|
||||
const setActiveBaseUrl = (baseUrl: string) => {
|
||||
activeBaseUrl = baseUrl;
|
||||
};
|
||||
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
||||
const request = (path: string, init?: RequestInit) =>
|
||||
fetchWithFallback(
|
||||
candidates,
|
||||
activeBaseUrl,
|
||||
setActiveBaseUrl,
|
||||
fetchAgent(
|
||||
normalizedBaseUrl,
|
||||
path,
|
||||
init,
|
||||
options.getAccessToken,
|
||||
@@ -265,7 +257,7 @@ export function createAgentApiClient(
|
||||
return token;
|
||||
} : undefined;
|
||||
const answerStateRequest = async (path: string, init?: RequestInit) => {
|
||||
const response = await fetchWithFallback(candidates, activeBaseUrl, setActiveBaseUrl, path, init,
|
||||
const response = await fetchAgent(normalizedBaseUrl, path, init,
|
||||
checkedAnswerStateToken, options.getProjectId);
|
||||
// An identity change while awaiting the network also invalidates the result.
|
||||
await checkedAnswerStateToken?.();
|
||||
@@ -275,7 +267,7 @@ export function createAgentApiClient(
|
||||
return {
|
||||
...createInteractionRequestApi(answerStateRequest),
|
||||
async getHealth(signal) {
|
||||
const response = await fetchWithFallback(candidates, activeBaseUrl, setActiveBaseUrl, "/health", { signal, cache: "no-store" }, undefined, undefined, "");
|
||||
const response = await fetchAgent(normalizedBaseUrl, "/health", { signal, cache: "no-store" }, undefined, undefined, "");
|
||||
if (!response.ok) throw new Error("Agent 服务暂不可用");
|
||||
const data: unknown = await response.json();
|
||||
if (!isRecord(data) || data.ok !== true || data.ready !== true) throw new Error("Agent 服务尚未就绪");
|
||||
@@ -579,19 +571,14 @@ export function createAgentApiClient(
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchWithFallback(
|
||||
baseUrls: string[],
|
||||
activeBaseUrl: string,
|
||||
setActiveBaseUrl: (baseUrl: string) => void,
|
||||
async function fetchAgent(
|
||||
baseUrl: string,
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
getAccessToken?: AccessTokenProvider,
|
||||
getProjectId?: () => Promise<string | undefined>,
|
||||
prefix = API_PATH
|
||||
) {
|
||||
const orderedBaseUrls = [activeBaseUrl, ...baseUrls.filter((item) => item !== activeBaseUrl)];
|
||||
let lastError: unknown;
|
||||
let lastResponse: Response | null = null;
|
||||
const accessToken = await getAccessToken?.();
|
||||
const projectId = await getProjectId?.();
|
||||
const hasContextHeaders = Boolean(accessToken || projectId);
|
||||
@@ -600,34 +587,7 @@ async function fetchWithFallback(
|
||||
if (projectId) headers?.set("X-Project-Id", projectId);
|
||||
const requestInit = hasContextHeaders ? { ...init, headers } : init;
|
||||
|
||||
for (const baseUrl of orderedBaseUrls) {
|
||||
try {
|
||||
const response = await fetch(`${baseUrl}${prefix}${path}`, requestInit);
|
||||
if (response.ok) {
|
||||
setActiveBaseUrl(baseUrl);
|
||||
return response;
|
||||
}
|
||||
|
||||
lastResponse = response;
|
||||
if (shouldFallbackOnHttpStatus(response.status) && baseUrl !== orderedBaseUrls[orderedBaseUrls.length - 1]) {
|
||||
await response.body?.cancel();
|
||||
continue;
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastResponse) {
|
||||
return lastResponse;
|
||||
}
|
||||
|
||||
throw lastError instanceof Error ? lastError : new Error("Agent API unavailable");
|
||||
}
|
||||
|
||||
function shouldFallbackOnHttpStatus(status: number) {
|
||||
return status === 404 || status === 405 || status === 502 || status === 503 || status === 504;
|
||||
return fetch(`${baseUrl}${prefix}${path}`, requestInit);
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
|
||||
Reference in New Issue
Block a user