修复确认生成后的任务列表对账
问题:客户端确认 Quote 后只刷新一次任务,遇到短暂投影延迟时任务列表为空且流程静默成功。 修复:按 quoteId 有界重试任务列表,合并 REST 与实时推送快照,缺任务时显示明确错误;补充 Store 与页面回归测试。
This commit is contained in:
@@ -67,6 +67,8 @@ type ImageWorkspaceState = {
|
||||
|
||||
let inFlightLoad: Promise<DesignWorkspaceBootstrap | null> | null = null;
|
||||
const TASK_FALLBACK_POLL_INTERVAL_MS = 15_000;
|
||||
const CONFIRMED_TASK_RECONCILE_ATTEMPTS = 5;
|
||||
const CONFIRMED_TASK_RECONCILE_INTERVAL_MS = 250;
|
||||
let activeTaskEventSource: EventSource | null = null;
|
||||
let activeTaskEventWorkspaceId: string | null = null;
|
||||
let taskStreamGeneration = 0;
|
||||
@@ -170,6 +172,18 @@ function sortTasks(tasks: DesignGenerationTask[]): DesignGenerationTask[] {
|
||||
));
|
||||
}
|
||||
|
||||
function mergeTasks(
|
||||
current: DesignGenerationTask[],
|
||||
incoming: DesignGenerationTask[],
|
||||
): DesignGenerationTask[] {
|
||||
const tasksById = new Map(current.map((task) => [task.taskId, task]));
|
||||
for (const task of incoming) {
|
||||
const existing = tasksById.get(task.taskId);
|
||||
if (!existing || existing.updatedAt <= task.updatedAt) tasksById.set(task.taskId, task);
|
||||
}
|
||||
return sortTasks([...tasksById.values()]);
|
||||
}
|
||||
|
||||
function unavailable(error: unknown): boolean {
|
||||
return error instanceof ImageWorkspaceApiError
|
||||
&& (error.status === 501 || error.code === IMAGE_WORKSPACE_UNAVAILABLE_CODE);
|
||||
@@ -598,7 +612,7 @@ export const useImageWorkspaceStore = create<ImageWorkspaceState>((set, get) =>
|
||||
if (get().activeWorkspaceId === workspaceId
|
||||
&& currentWorkspace?.workspaceId === workspaceId
|
||||
&& currentWorkspace.viewRevision === requestedViewRevision) {
|
||||
set({ tasks: sortTasks(tasks) });
|
||||
set((state) => ({ tasks: mergeTasks(state.tasks, tasks) }));
|
||||
for (const task of tasks) {
|
||||
const key = taskRevisionKey(workspaceId, task.taskId);
|
||||
taskEventRevisions.set(
|
||||
@@ -669,7 +683,30 @@ export const useImageWorkspaceStore = create<ImageWorkspaceState>((set, get) =>
|
||||
);
|
||||
if (get().activeWorkspaceId === workspace.workspaceId) {
|
||||
applyWorkspace(updated);
|
||||
await get().refreshTasks().catch(() => []);
|
||||
let confirmedTaskVisible = get().tasks.some((task) => task.quoteId === quoteId);
|
||||
for (
|
||||
let attempt = 0;
|
||||
!confirmedTaskVisible && attempt < CONFIRMED_TASK_RECONCILE_ATTEMPTS;
|
||||
attempt += 1
|
||||
) {
|
||||
if (get().activeWorkspaceId !== workspace.workspaceId) return updated;
|
||||
const refreshed = await get().refreshTasks();
|
||||
if (get().activeWorkspaceId !== workspace.workspaceId) return updated;
|
||||
confirmedTaskVisible = refreshed.some((task) => task.quoteId === quoteId)
|
||||
|| get().tasks.some((task) => task.quoteId === quoteId);
|
||||
if (!confirmedTaskVisible && attempt + 1 < CONFIRMED_TASK_RECONCILE_ATTEMPTS) {
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(resolve, CONFIRMED_TASK_RECONCILE_INTERVAL_MS);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!confirmedTaskVisible) {
|
||||
throw new ImageWorkspaceApiError(
|
||||
502,
|
||||
'generation_task_not_visible',
|
||||
'生成已确认,但任务列表同步超时。请刷新项目查看,不要重复确认。',
|
||||
);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user