• Prepares batch sync operations in a worker (grouping, steps, variables).

    Parameters

    • message: BatchSyncMessage

      Worker message containing entries to sync.

    • activeTasks: Set<string>

      Set tracking active task IDs for cancellation.

    Returns Promise<void>

    Promise that posts result and progress messages.

    export async function handleBatchSync(
    message: BatchSyncMessage,
    activeTasks: Set<string>,
    ): Promise<void> {
    const { taskId, entries } = message.payload;

    try {
    activeTasks.add(taskId);

    console.info(
    `[Worker] 📦 Starting batch sync pre-processing for ${entries.length} entries`,
    );

    const startTime = performance.now();

    if (!activeTasks.has(taskId)) {
    console.warn(
    `[Worker] ⚠️ Batch sync task ${taskId} was cancelled during organizing`,
    );
    globalThis.postMessage({
    type: "BATCH_SYNC_CANCELLED",
    payload: {
    taskId,
    phase: "organizing",
    },
    });
    return;
    }

    const progressMsg1: BatchSyncProgressMessage = {
    type: "BATCH_SYNC_PROGRESS",
    payload: {
    taskId,
    phase: "organizing",
    processed: 0,
    total: entries.length,
    },
    };
    globalThis.postMessage(progressMsg1);

    const entriesByMediaId = organizeEntriesByMediaIdForWorker(entries);
    const mediaIds = Object.keys(entriesByMediaId)
    .map(Number)
    .sort((a, b) => a - b);

    if (!activeTasks.has(taskId)) {
    console.warn(
    `[Worker] ⚠️ Batch sync task ${taskId} was cancelled during building`,
    );
    globalThis.postMessage({
    type: "BATCH_SYNC_CANCELLED",
    payload: {
    taskId,
    phase: "building",
    },
    });
    return;
    }

    const progressMsg2: BatchSyncProgressMessage = {
    type: "BATCH_SYNC_PROGRESS",
    payload: {
    taskId,
    phase: "building",
    processed: 0,
    total: mediaIds.length,
    },
    };
    globalThis.postMessage(progressMsg2);

    const operations: PreparedSyncOperation[] = [];
    const failedEntries: Array<{ mediaId: number; error: string }> = [];
    let totalApiCallsEstimate = 0;

    for (let i = 0; i < mediaIds.length; i++) {
    if (!activeTasks.has(taskId)) {
    console.warn(
    `[Worker] ⚠️ Batch sync task ${taskId} was cancelled during building`,
    );
    globalThis.postMessage({
    type: "BATCH_SYNC_CANCELLED",
    payload: {
    taskId,
    phase: "building",
    },
    });
    return;
    }

    const mediaId = mediaIds[i];
    const mediaEntries = entriesByMediaId[mediaId];

    try {
    const steps = mediaEntries
    .map((e) => e.syncMetadata?.step || 1)
    .filter((step, idx, arr) => arr.indexOf(step) === idx)
    .sort((a, b) => a - b);

    const variables = mediaEntries.map((entry) =>
    buildGraphQLVariablesForEntry(entry, entry.syncMetadata?.step || 1),
    );

    const operation: PreparedSyncOperation = {
    mediaId,
    entries: mediaEntries,
    steps,
    variables,
    estimatedApiCalls: steps.length,
    };

    operations.push(operation);
    totalApiCallsEstimate += steps.length;

    if ((i + 1) % 10 === 0) {
    const progressMsg: BatchSyncProgressMessage = {
    type: "BATCH_SYNC_PROGRESS",
    payload: {
    taskId,
    phase: "building",
    processed: i + 1,
    total: mediaIds.length,
    currentMediaId: mediaId,
    },
    };
    globalThis.postMessage(progressMsg);
    }
    } catch (error) {
    failedEntries.push({
    mediaId,
    error: error instanceof Error ? error.message : String(error),
    });
    }
    }

    if (!activeTasks.has(taskId)) {
    console.warn(
    `[Worker] ⚠️ Batch sync task ${taskId} was cancelled before completion`,
    );
    globalThis.postMessage({
    type: "BATCH_SYNC_CANCELLED",
    payload: {
    taskId,
    phase: "completion",
    },
    });
    return;
    }

    const progressMsg3: BatchSyncProgressMessage = {
    type: "BATCH_SYNC_PROGRESS",
    payload: {
    taskId,
    phase: "ready",
    processed: mediaIds.length,
    total: mediaIds.length,
    },
    };
    globalThis.postMessage(progressMsg3);

    const totalTime = performance.now() - startTime;

    const resultMsg: BatchSyncResultMessage = {
    type: "BATCH_SYNC_RESULT",
    payload: {
    taskId,
    operations,
    totalApiCallsEstimate,
    failedEntries,
    },
    };

    console.info(
    `[Worker] ✅ Batch sync pre-processing completed: ${operations.length} operations, ${totalApiCallsEstimate} estimated API calls, ${failedEntries.length} failures (${totalTime.toFixed(2)}ms)`,
    );

    globalThis.postMessage(resultMsg);
    } catch (error) {
    console.error(`[Worker] ❌ Error in batch sync task ${taskId}:`, error);
    globalThis.postMessage({
    type: "ERROR",
    payload: {
    taskId,
    error: getErrorDetails(error),
    },
    });
    } finally {
    activeTasks.delete(taskId);
    }
    }