Worker message with matches and detection settings.
Set tracking active task IDs.
Void; posts DUPLICATE_DETECTION_RESULT or ERROR.
export function handleDuplicateDetection(
message: DuplicateDetectionMessage,
activeTasks: Set<string>,
): void {
const { taskId, matches, ignoredDuplicateIds } = message.payload;
activeTasks.add(taskId);
console.debug(
`[Worker] 🔍 Starting duplicate detection for task ${taskId} (${matches.length} matches)`,
);
const startTime = performance.now();
try {
const ignoredIds = new Set(ignoredDuplicateIds);
const { map: anilistIdMap, comparisonCount } = buildAnilistIdMap(
matches,
taskId,
activeTasks,
);
if (!activeTasks.has(taskId)) {
console.warn(
`[Worker] ⚠️ Duplicate detection task ${taskId} was cancelled after ${comparisonCount} comparisons`,
);
globalThis.postMessage({
type: "DUPLICATE_DETECTION_CANCELLED",
payload: {
taskId,
comparisonsCompleted: comparisonCount,
},
});
return;
}
const progressMsg: DuplicateDetectionProgressMessage = {
type: "DUPLICATE_DETECTION_PROGRESS",
payload: {
taskId,
current: comparisonCount,
total: matches.length,
message: "Identifying duplicate groups",
},
};
globalThis.postMessage(progressMsg);
const duplicates = extractDuplicates(anilistIdMap, ignoredIds);
if (!activeTasks.has(taskId)) {
console.warn(
`[Worker] ⚠️ Duplicate detection task ${taskId} was cancelled before completion`,
);
globalThis.postMessage({
type: "DUPLICATE_DETECTION_CANCELLED",
payload: {
taskId,
stage: "completion",
},
});
return;
}
const processingTimeMs = performance.now() - startTime;
const resultMsg: DuplicateDetectionResultMessage = {
type: "DUPLICATE_DETECTION_RESULT",
payload: {
taskId,
duplicates,
timing: {
processingTimeMs,
comparisonCount,
},
},
};
console.info(
`[Worker] ✅ Duplicate detection task ${taskId} completed (${duplicates.length} groups found, ${comparisonCount} comparisons, ${processingTimeMs.toFixed(2)}ms)`,
);
globalThis.postMessage(resultMsg);
} catch (error) {
console.error(
`[Worker] ❌ Error in duplicate detection task ${taskId}:`,
error,
);
globalThis.postMessage({
type: "ERROR",
payload: {
taskId,
error: getErrorDetails(error),
},
});
} finally {
activeTasks.delete(taskId);
}
}
Detects duplicate mappings where one AniList ID maps to multiple Kenmei titles.