86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
function _normalizeJobId(jobId: any) {
|
|
return String(jobId || "").trim();
|
|
}
|
|
|
|
function _assetFileKey(detail: any) {
|
|
const filename = String(detail?.filename || "").trim();
|
|
const filepath = String(detail?.filepath || "").trim();
|
|
const subfolder = String(detail?.subfolder || "").trim();
|
|
const type = String(detail?.type || detail?.source || "output")
|
|
.trim()
|
|
.toLowerCase();
|
|
const rootId = String(detail?.root_id || detail?.custom_root_id || "").trim();
|
|
return `${type}|${rootId}|${subfolder}|${filename || filepath}`;
|
|
}
|
|
|
|
function _copyWithJobId(detail: any, jobId: any) {
|
|
if (!jobId) return detail;
|
|
if (String(detail?.job_id || "").trim() === jobId) return detail;
|
|
return { ...(detail || {}), job_id: jobId };
|
|
}
|
|
|
|
export function createLiveAssetGate(): Record<string, any> {
|
|
const pendingJobs = new Map();
|
|
|
|
function markPendingJob(jobId: any, { files = [], expectedCount = null } = {}) {
|
|
const normalizedJobId = _normalizeJobId(jobId);
|
|
if (!normalizedJobId) return;
|
|
const fileKeys = new Set();
|
|
for (const file of Array.isArray(files) ? files : []) {
|
|
const key = _assetFileKey(file);
|
|
if (key) fileKeys.add(key);
|
|
}
|
|
pendingJobs.set(normalizedJobId, {
|
|
expectedCount: Math.max(0, Number(expectedCount ?? fileKeys.size) || 0),
|
|
fileKeys,
|
|
markedAt: Date.now(),
|
|
});
|
|
}
|
|
|
|
function clearPendingJob(jobId: any) {
|
|
const normalizedJobId = _normalizeJobId(jobId);
|
|
if (!normalizedJobId) return;
|
|
pendingJobs.delete(normalizedJobId);
|
|
}
|
|
|
|
function resolveJobId(detail: any) {
|
|
const explicit = _normalizeJobId(detail?.job_id);
|
|
if (explicit) return explicit;
|
|
const key = _assetFileKey(detail);
|
|
if (!key) return "";
|
|
let bestJobId = "";
|
|
let oldestTime = Infinity;
|
|
for (const [jobId, meta] of pendingJobs.entries()) {
|
|
if (meta?.fileKeys?.has?.(key) && (meta.markedAt ?? Infinity) < oldestTime) {
|
|
oldestTime = meta.markedAt ?? Infinity;
|
|
bestJobId = jobId;
|
|
}
|
|
}
|
|
return bestJobId;
|
|
}
|
|
|
|
function prepare(detail: any) {
|
|
const jobId = resolveJobId(detail);
|
|
if (!jobId) return { detail, jobId: "", defer: false };
|
|
const normalizedDetail = _copyWithJobId(detail, jobId);
|
|
const pending = pendingJobs.get(jobId);
|
|
if (!pending) return { detail: normalizedDetail, jobId, defer: false };
|
|
const stackId = String(normalizedDetail?.stack_id || "").trim();
|
|
const expectedCount = Math.max(0, Number(pending?.expectedCount || 0) || 0);
|
|
const isMultiOutput = expectedCount > 1;
|
|
return {
|
|
detail: normalizedDetail,
|
|
jobId,
|
|
defer: isMultiOutput && !stackId,
|
|
};
|
|
}
|
|
|
|
return {
|
|
markPendingJob,
|
|
clearPendingJob,
|
|
resolveJobId,
|
|
prepare,
|
|
_pendingJobs: pendingJobs,
|
|
};
|
|
}
|