All files / extensions/cornerstone/src/utils initWebWorkerProgressHandler.ts

75.67% Statements 28/37
100% Branches 10/10
100% Functions 4/4
75.67% Lines 28/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                      204x       204x 3763x     204x   3871x   3871x 3871x     3871x 108x     3763x   3763x   495x 10x 10x 10x                         10x 10x                                         485x       3268x   172x   172x   6x 6x     6x   6x               3871x 6x 6x                      
import { eventTarget, EVENTS } from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
 
/**
 * Initializes a handler for web worker progress events.
 * Tracks active worker tasks and shows notifications for their progress.
 *
 * @param uiNotificationService - The UI notification service for showing progress notifications
 */
export function initializeWebWorkerProgressHandler(uiNotificationService: any) {
  // Use a single map to track all active worker tasks
  const activeWorkerTasks = new Map();
 
  // Create a normalized task key that doesn't include the random ID
  // This helps us identify and deduplicate the same type of task
  const getNormalizedTaskKey = (type: string) => {
    return `worker-task-${type.toLowerCase().replace(/\s+/g, '-')}`;
  };
 
  eventTarget.addEventListener(EVENTS.WEB_WORKER_PROGRESS, ({ detail }) => {
    let normalizedKey: string | undefined;
    let shouldCleanup = false;
 
    try {
      const { progress, type, id } = detail;
 
      // Skip notifications for compute statistics
      if (type === cornerstoneTools.Enums.WorkerTypes.COMPUTE_STATISTICS) {
        return;
      }
 
      normalizedKey = getNormalizedTaskKey(type);
 
      if (progress === 0) {
        // Check if we're already tracking a task of this type
        if (!activeWorkerTasks.has(normalizedKey)) {
          const progressPromise = new Promise((resolve, reject) => {
            try {
              activeWorkerTasks.set(normalizedKey, {
                resolve,
                reject,
                originalId: id,
                type,
              });
            } catch (error) {
              console.error(`Error setting active worker task for type "${type}":`, error);
              reject(error);
              throw error; // Re-throw to trigger outer catch and cleanup
            }
          });
 
          try {
            uiNotificationService.show({
              id: normalizedKey, // Use the normalized key as ID for better deduplication
              title: `${type}`,
              message: `Computing...`,
              autoClose: false,
              allowDuplicates: false,
              deduplicationInterval: 60000, // 60 seconds - prevent frequent notifications of same type
              promise: progressPromise,
              promiseMessages: {
                loading: `Computing...`,
                success: `Completed successfully`,
                error: 'Web Worker failed',
              },
            });
          } catch (error) {
            console.error(`Error showing web worker notification for type "${type}":`, error);
            shouldCleanup = true;
            throw error;
          }
        } else {
          // Already tracking this type of task, just let it continue
          console.debug(`Already tracking a "${type}" task, skipping duplicate notification`);
        }
      }
      // Task completed
      else if (progress === 100) {
        // Check if we have this task type in our tracking map
        const taskData = activeWorkerTasks.get(normalizedKey);
 
        if (taskData) {
          // Resolve the promise to update the notification
          const { resolve } = taskData;
          resolve({ progress, type });
 
          // Mark for cleanup
          shouldCleanup = true;
 
          console.debug(`Worker task "${type}" completed successfully`);
        }
      }
    } catch (error) {
      console.error(`Error in web worker progress handler for type "${detail?.type}":`, error);
      shouldCleanup = true;
    } finally {
      // Clean up if needed
      if (shouldCleanup && normalizedKey) {
        try {
          activeWorkerTasks.delete(normalizedKey);
        } catch (cleanupError) {
          console.error(
            `Error cleaning up active worker task for type "${detail?.type}":`,
            cleanupError
          );
        }
      }
    }
  });
}