perf(code-queue): optimize first-load latency with skipTrace and caching
- Frontend: initial task list load passes skipTrace=1 to skip trace stats, then fetches full data in background and merges into state - Code-queue: respect skipTrace=1 param to skip traceStatsForTasks call - Code-queue: add 8s in-memory cache for OA trace stats (per scope ID) - Code-queue: add 10s in-memory cache for database statistics summary These changes reduce first-paint time by eliminating the blocking trace stats HTTP call on initial load. Trace stats populate asynchronously after the task list renders.
This commit is contained in:
@@ -317,14 +317,14 @@ function queueRunnableTaskId(queueRows: any[], queueId: string, rows: any[]): st
|
||||
async function loadTaskList(apiBaseUrl: string, queueId = allQueuesId, searchQuery = ""): Promise<any> {
|
||||
return requestJson(codexApi(
|
||||
apiBaseUrl,
|
||||
`/api/tasks/overview?limit=${codexInitialTaskLimit}&transcriptLimit=1&compact=1&selected=0${taskListQuerySuffix(queueId, searchQuery)}`,
|
||||
`/api/tasks/overview?limit=${codexInitialTaskLimit}&transcriptLimit=1&compact=1&selected=0&skipTrace=1${taskListQuerySuffix(queueId, searchQuery)}`,
|
||||
), codexNoCacheOptions());
|
||||
}
|
||||
|
||||
async function loadTaskOverview(apiBaseUrl: string, preferId: string, afterSeq = 0, queueId = allQueuesId, searchQuery = ""): Promise<any> {
|
||||
async function loadTaskOverview(apiBaseUrl: string, preferId: string, afterSeq = 0, queueId = allQueuesId, searchQuery = "", skipTrace = false): Promise<any> {
|
||||
return requestJson(codexApi(
|
||||
apiBaseUrl,
|
||||
`/api/tasks/overview?limit=${codexInitialTaskLimit}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0, afterSeq)))}&preferId=${encodeURIComponent(preferId)}${taskListQuerySuffix(queueId, searchQuery)}`,
|
||||
`/api/tasks/overview?limit=${codexInitialTaskLimit}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0, afterSeq)))}&preferId=${encodeURIComponent(preferId)}${skipTrace ? "&skipTrace=1" : ""}${taskListQuerySuffix(queueId, searchQuery)}`,
|
||||
), codexNoCacheOptions());
|
||||
}
|
||||
|
||||
@@ -2528,7 +2528,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi
|
||||
const requestedTranscript = Array.isArray(requestedCached?.task?.transcript) ? requestedCached.task.transcript : [];
|
||||
const overviewAfterSeq = transcriptResumeSeq(requestedTranscript);
|
||||
let tasksResult = null;
|
||||
tasksResult = await loadTaskOverview(apiBaseUrl, requestedId, overviewAfterSeq, queueFilterId);
|
||||
tasksResult = await loadTaskOverview(apiBaseUrl, requestedId, overviewAfterSeq, queueFilterId, "", true);
|
||||
if (token !== queueLoadTokenRef.current) {
|
||||
if (trackLoad) trackedLoadInFlightRef.current = false;
|
||||
return;
|
||||
@@ -2608,6 +2608,19 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi
|
||||
// cards are shown for historical multi-attempt sessions too.
|
||||
void ensureTraceSummary(nextId, false, trackLoad ? startedAt : undefined, trackLoad ? queueMs : undefined)
|
||||
.catch((err) => setError(errorText(err, "加载 Codex Trace Summary 失败")));
|
||||
// Background refresh with trace stats to populate stepCount in task list
|
||||
void loadTaskOverview(apiBaseUrl, requestedId, overviewAfterSeq, queueFilterId, "", false)
|
||||
.then((full: any) => {
|
||||
if (token !== queueLoadTokenRef.current) return;
|
||||
const fullRows = taskRows(full);
|
||||
if (fullRows.length > 0) {
|
||||
setTasksData((previous: any) => {
|
||||
const mergedRows = mergeTaskRowsPreferLatest([taskRows(previous), fullRows], activeSortId);
|
||||
return { ...previous, tasks: applyLocalReadStateToRows(mergedRows) };
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
return;
|
||||
}
|
||||
if (trackLoad) {
|
||||
|
||||
Reference in New Issue
Block a user