c5295a619c
空生成任务列表不再保持四秒轮询 读取资源字节优先通过read-url直连OSS 保留read-bytes作为OSS读取失败兜底 更新资产导出与项目记忆文档口径
226 lines
6.1 KiB
TypeScript
226 lines
6.1 KiB
TypeScript
import type {
|
|
ExternalGenerationJobStatusRecord,
|
|
ExternalGenerationQueueOverview,
|
|
ExternalGenerationTaskRecord,
|
|
} from '../../../packages/shared/src/contracts/externalGeneration';
|
|
|
|
export type ExternalGenerationQueueStatus = {
|
|
currentStatus?: 'queued' | 'running' | 'completed' | 'failed' | null;
|
|
currentProgress?: number | null;
|
|
pendingCount?: number | null;
|
|
runningCount?: number | null;
|
|
tasks?: ExternalGenerationTaskRecord[] | null;
|
|
unacknowledgedTerminalCount?: number | null;
|
|
};
|
|
|
|
export type ExternalGenerationQueueTaskPresentation = {
|
|
id: string;
|
|
title: string;
|
|
statusLabel: string;
|
|
priceLabel: string;
|
|
detail: string;
|
|
tone: 'profile' | 'danger' | 'success';
|
|
};
|
|
|
|
export type ExternalGenerationQueuePresentation = {
|
|
statusLabel: string | null;
|
|
progressLabel: string | null;
|
|
pendingLabel: string;
|
|
runningLabel: string;
|
|
pendingCount: number;
|
|
runningCount: number;
|
|
unacknowledgedTerminalCount: number;
|
|
progress: number | null;
|
|
tasks: ExternalGenerationQueueTaskPresentation[];
|
|
shouldShow: boolean;
|
|
};
|
|
|
|
export function buildExternalGenerationQueueStatus(
|
|
overview: ExternalGenerationQueueOverview | null,
|
|
job: ExternalGenerationJobStatusRecord | null,
|
|
tasks: ExternalGenerationTaskRecord[] | null = null,
|
|
): ExternalGenerationQueueStatus | null {
|
|
if (!overview && !job && !tasks?.length) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
currentStatus: job?.status ?? null,
|
|
currentProgress: job?.progress ?? null,
|
|
pendingCount: overview?.pendingCount ?? null,
|
|
runningCount: overview?.runningCount ?? null,
|
|
unacknowledgedTerminalCount:
|
|
overview?.unacknowledgedTerminalCount ?? null,
|
|
tasks,
|
|
};
|
|
}
|
|
|
|
function isActiveExternalGenerationStatus(
|
|
status: ExternalGenerationQueueStatus['currentStatus'],
|
|
) {
|
|
return status === 'queued' || status === 'running';
|
|
}
|
|
|
|
function isUnacknowledgedExternalGenerationTerminalTask(
|
|
task: ExternalGenerationTaskRecord,
|
|
) {
|
|
return (
|
|
(task.status === 'completed' || task.status === 'failed') &&
|
|
!task.notificationAcknowledgedAt
|
|
);
|
|
}
|
|
|
|
export function shouldUseFastExternalGenerationTaskPolling(
|
|
status: ExternalGenerationQueueStatus | null | undefined,
|
|
) {
|
|
const pendingCount = normalizeExternalGenerationQueueCount(
|
|
status?.pendingCount,
|
|
);
|
|
const runningCount = normalizeExternalGenerationQueueCount(
|
|
status?.runningCount,
|
|
);
|
|
const unacknowledgedTerminalCount = normalizeExternalGenerationQueueCount(
|
|
status?.unacknowledgedTerminalCount,
|
|
);
|
|
|
|
return Boolean(
|
|
isActiveExternalGenerationStatus(status?.currentStatus ?? null) ||
|
|
pendingCount > 0 ||
|
|
runningCount > 0 ||
|
|
unacknowledgedTerminalCount > 0 ||
|
|
(status?.tasks ?? []).some(
|
|
(task) =>
|
|
task.status === 'queued' ||
|
|
task.status === 'running' ||
|
|
isUnacknowledgedExternalGenerationTerminalTask(task),
|
|
),
|
|
);
|
|
}
|
|
|
|
export function resolveExternalGenerationQueueStatusLabel(
|
|
status: ExternalGenerationQueueStatus['currentStatus'],
|
|
) {
|
|
if (status === 'queued') {
|
|
return '排队中';
|
|
}
|
|
|
|
if (status === 'running') {
|
|
return '生成中';
|
|
}
|
|
|
|
if (status === 'failed') {
|
|
return '生成失败';
|
|
}
|
|
|
|
if (status === 'completed') {
|
|
return '已完成';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function resolveExternalGenerationQueueOverviewLabel(
|
|
pendingCount: number,
|
|
runningCount: number,
|
|
) {
|
|
if (runningCount > 0) {
|
|
return '生成中';
|
|
}
|
|
|
|
if (pendingCount > 0) {
|
|
return '排队中';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function normalizeExternalGenerationQueueCount(
|
|
value: number | null | undefined,
|
|
) {
|
|
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
return 0;
|
|
}
|
|
|
|
return Math.max(0, Math.round(value));
|
|
}
|
|
|
|
export function normalizeExternalGenerationQueueProgress(
|
|
value: number | null | undefined,
|
|
) {
|
|
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
return null;
|
|
}
|
|
|
|
return Math.max(0, Math.min(100, Math.round(value)));
|
|
}
|
|
|
|
export function buildExternalGenerationTaskPresentation(
|
|
task: ExternalGenerationTaskRecord,
|
|
): ExternalGenerationQueueTaskPresentation {
|
|
const statusLabel = resolveExternalGenerationQueueStatusLabel(task.status) ?? '待处理';
|
|
return {
|
|
id: task.jobId,
|
|
title: task.requestLabel.trim() || task.jobKind,
|
|
statusLabel,
|
|
priceLabel:
|
|
task.priceMudPoints > 0 ? `${task.priceMudPoints}泥点` : '未计费',
|
|
detail: task.error?.trim() || task.phaseDetail || task.updatedAt,
|
|
tone:
|
|
task.status === 'failed'
|
|
? 'danger'
|
|
: task.status === 'completed'
|
|
? 'success'
|
|
: 'profile',
|
|
};
|
|
}
|
|
|
|
export function buildExternalGenerationQueuePresentation(
|
|
status: ExternalGenerationQueueStatus | null | undefined,
|
|
): ExternalGenerationQueuePresentation {
|
|
const pendingCount = normalizeExternalGenerationQueueCount(
|
|
status?.pendingCount,
|
|
);
|
|
const runningCount = normalizeExternalGenerationQueueCount(
|
|
status?.runningCount,
|
|
);
|
|
const unacknowledgedTerminalCount = normalizeExternalGenerationQueueCount(
|
|
status?.unacknowledgedTerminalCount,
|
|
);
|
|
const progress = normalizeExternalGenerationQueueProgress(
|
|
status?.currentProgress,
|
|
);
|
|
const isCompletedCurrentJob = status?.currentStatus === 'completed';
|
|
const currentStatusLabel = resolveExternalGenerationQueueStatusLabel(
|
|
status?.currentStatus ?? null,
|
|
);
|
|
const overviewStatusLabel = resolveExternalGenerationQueueOverviewLabel(
|
|
pendingCount,
|
|
runningCount,
|
|
);
|
|
const statusLabel = isCompletedCurrentJob
|
|
? overviewStatusLabel
|
|
: (currentStatusLabel ?? overviewStatusLabel);
|
|
const progressValue = isCompletedCurrentJob ? null : progress;
|
|
|
|
return {
|
|
statusLabel,
|
|
progressLabel: progressValue == null ? null : `${progressValue}%`,
|
|
pendingLabel: pendingCount.toString(),
|
|
runningLabel: runningCount.toString(),
|
|
pendingCount,
|
|
runningCount,
|
|
unacknowledgedTerminalCount,
|
|
progress: progressValue,
|
|
tasks: (status?.tasks ?? [])
|
|
.slice(0, 5)
|
|
.map(buildExternalGenerationTaskPresentation),
|
|
shouldShow: Boolean(
|
|
statusLabel ||
|
|
pendingCount > 0 ||
|
|
runningCount > 0 ||
|
|
unacknowledgedTerminalCount > 0 ||
|
|
(status?.tasks?.length ?? 0) > 0,
|
|
),
|
|
};
|
|
}
|