Fix AI reindex job execution and progress
Some checks failed
docker-images / resolve-build-targets (push) Failing after 1s
docker-images / build-and-push (admin) (push) Has been cancelled
docker-images / submit-indexnow (push) Has been cancelled
docker-images / build-and-push (backend) (push) Has been cancelled
docker-images / build-and-push (frontend) (push) Has been cancelled
ui-regression / playwright-regression (push) Has been cancelled
Some checks failed
docker-images / resolve-build-targets (push) Failing after 1s
docker-images / build-and-push (admin) (push) Has been cancelled
docker-images / submit-indexnow (push) Has been cancelled
docker-images / build-and-push (backend) (push) Has been cancelled
docker-images / build-and-push (frontend) (push) Has been cancelled
ui-regression / playwright-regression (push) Has been cancelled
This commit is contained in:
116
admin/src/lib/worker-progress.ts
Normal file
116
admin/src/lib/worker-progress.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { WorkerJobRecord } from "@/lib/types";
|
||||
|
||||
type WorkerProgressShape = {
|
||||
phase?: string;
|
||||
message?: string;
|
||||
total_chunks?: number;
|
||||
processed_chunks?: number;
|
||||
total_batches?: number;
|
||||
current_batch?: number;
|
||||
batch_size?: number;
|
||||
percent?: number;
|
||||
};
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | null {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function asText(value: unknown): string | null {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : null;
|
||||
}
|
||||
|
||||
export function getWorkerProgress(
|
||||
job: Pick<WorkerJobRecord, "result">,
|
||||
): WorkerProgressShape | null {
|
||||
const result = asRecord(job.result);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nested = asRecord(result.progress);
|
||||
const source = nested ?? result;
|
||||
const percent = asNumber(source.percent);
|
||||
const totalChunks = asNumber(source.total_chunks);
|
||||
const processedChunks = asNumber(source.processed_chunks);
|
||||
const totalBatches = asNumber(source.total_batches);
|
||||
const currentBatch = asNumber(source.current_batch);
|
||||
const batchSize = asNumber(source.batch_size);
|
||||
const phase = asText(source.phase) ?? asText(result.phase) ?? undefined;
|
||||
const message = asText(source.message) ?? asText(result.message) ?? undefined;
|
||||
|
||||
if (
|
||||
percent === null &&
|
||||
totalChunks === null &&
|
||||
processedChunks === null &&
|
||||
totalBatches === null &&
|
||||
currentBatch === null &&
|
||||
batchSize === null &&
|
||||
!phase &&
|
||||
!message
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
phase,
|
||||
message,
|
||||
total_chunks: totalChunks ?? undefined,
|
||||
processed_chunks: processedChunks ?? undefined,
|
||||
total_batches: totalBatches ?? undefined,
|
||||
current_batch: currentBatch ?? undefined,
|
||||
batch_size: batchSize ?? undefined,
|
||||
percent: percent ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function formatWorkerProgress(
|
||||
job: Pick<WorkerJobRecord, "result">,
|
||||
): string | null {
|
||||
const progress = getWorkerProgress(job);
|
||||
if (!progress) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const percentText =
|
||||
typeof progress.percent === "number"
|
||||
? `${Math.max(0, Math.min(100, Math.round(progress.percent)))}%`
|
||||
: null;
|
||||
const chunkText =
|
||||
typeof progress.processed_chunks === "number" &&
|
||||
typeof progress.total_chunks === "number"
|
||||
? `${progress.processed_chunks}/${progress.total_chunks} 分块`
|
||||
: null;
|
||||
const batchText =
|
||||
typeof progress.current_batch === "number" &&
|
||||
typeof progress.total_batches === "number" &&
|
||||
progress.total_batches > 0
|
||||
? `第 ${progress.current_batch}/${progress.total_batches} 批`
|
||||
: null;
|
||||
|
||||
const details = [percentText, chunkText, batchText]
|
||||
.filter(Boolean)
|
||||
.join(" · ");
|
||||
|
||||
if (progress.message && details) {
|
||||
return `${progress.message} ${details}`;
|
||||
}
|
||||
|
||||
return progress.message ?? (details || null);
|
||||
}
|
||||
Reference in New Issue
Block a user