Kenmei manga to match.
Candidate AniList entries keyed by ID.
Matching engine configuration overrides.
OptionalprogressCallback: (current: number, total: number, currentTitle?: string) => voidOptional progress callback.
Whether we should try workers (default: true).
Cancellable execution descriptor.
export function executeMatchingWithWorkers(
kenmeiMangaList: KenmeiManga[],
anilistCandidatesMap: Map<string, AniListManga[]>,
config: Partial<MatchEngineConfig> = {},
progressCallback?: (
current: number,
total: number,
currentTitle?: string,
) => void,
shouldUseWorkers = true,
): CancellableExecution {
// Generate task ID upfront to ensure consistency and eliminate race condition
// This ID is passed to the pool and used for all cancellation operations
const taskId = `task-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
const pool = shouldUseWorkers ? getWorkerPool() : null;
const promise = (async () => {
// Check if workers should be used
if (shouldUseWorkers && pool) {
try {
// Pass the upfront taskId to ensure pool uses same ID for all tracking
const execution = await pool.executeMatchBatch(
kenmeiMangaList,
anilistCandidatesMap,
config,
progressCallback,
taskId,
);
// Return the promise from the execution
return await execution.promise;
} catch (error) {
console.warn(
"Worker execution failed, falling back to main thread:",
error,
);
// Fall through to main thread execution
}
}
// Fallback to main thread execution
return executeMatchingOnMainThread(
kenmeiMangaList,
anilistCandidatesMap,
config,
progressCallback,
);
})();
return {
promise,
taskId,
cancel: () => {
// Always use the upfront taskId - it's guaranteed to be valid
// For sync fallback (no pool), this is a safe no-op
if (pool) {
pool.cancelBatch(taskId);
}
},
};
}
Executes batch matching via workers when possible, falling back to main thread.