• Executes batch matching via workers when possible, falling back to main thread.

    Parameters

    • kenmeiMangaList: KenmeiManga[]

      Kenmei manga to match.

    • anilistCandidatesMap: Map<string, AniListManga[]>

      Candidate AniList entries keyed by ID.

    • config: Partial<MatchEngineConfig> = {}

      Matching engine configuration overrides.

    • OptionalprogressCallback: (current: number, total: number, currentTitle?: string) => void

      Optional progress callback.

    • shouldUseWorkers: boolean = true

      Whether we should try workers (default: true).

    Returns CancellableExecution

    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);
    }
    },
    };
    }