All files / src/hooks sessionWorkerManager.ts

16.36% Statements 9/55
3.84% Branches 1/26
14.28% Functions 2/14
16.98% Lines 9/53

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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126        533x 533x 533x 533x 533x           533x 533x   533x                                                                                                                                                                                                                     533x  
// Worker manager singleton to ensure only one Web Worker instance
type SessionWorkerListener = (type: string, data?: unknown) => void;
 
class SessionWorkerManager {
  private static instance: SessionWorkerManager | null = null;
  private worker: Worker | null = null;
  private workerId: string | null = null;
  private isMonitoring = false;
  private listeners: Set<SessionWorkerListener> = new Set();
 
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  private constructor() {}
 
  static getInstance(): SessionWorkerManager {
    Eif (!SessionWorkerManager.instance) {
      SessionWorkerManager.instance = new SessionWorkerManager();
    }
    return SessionWorkerManager.instance;
  }
 
  initializeWorker(): boolean {
    // If worker already exists, don't create a new one
    if (this.worker) {
      return true;
    }
 
    // Check if Web Workers are supported
    if (typeof Worker === "undefined") {
      console.warn("Web Workers not supported");
      return false;
    }
 
    try {
      this.workerId = Math.random().toString(36).substr(2, 9);
 
      this.worker = new Worker("/session-worker.js");
 
      this.worker.onmessage = (e) => {
        const { type, data } = e.data;
 
        if (type === "CHECK_SESSION") {
          const sessionStartTime = localStorage.getItem("session_start_time");
          const currentTime = Date.now();
 
          if (this.worker) {
            this.worker.postMessage({
              type: "SESSION_STATUS",
              data: { sessionStartTime, currentTime },
            });
          }
        }
 
        this.listeners.forEach((listener) => listener(type, data));
      };
 
      this.worker.onerror = (error) => {
        console.error(
          "Session worker failed, worker ID:",
          this.workerId,
          error,
        );
        this.listeners.forEach((listener) => listener("WORKER_ERROR", error));
      };
 
      return true;
    } catch (error) {
      console.error("Failed to create session worker:", error);
      return false;
    }
  }
 
  startMonitoring(): void {
    if (!this.worker) {
      if (!this.initializeWorker()) {
        return;
      }
    }
 
    if (!this.isMonitoring && this.worker) {
      this.worker.postMessage({ type: "START_MONITORING" });
      this.isMonitoring = true;
    }
  }
 
  stopMonitoring(): void {
    if (this.worker && this.isMonitoring) {
      this.worker.postMessage({ type: "STOP_MONITORING" });
      this.isMonitoring = false;
    }
  }
 
  addListener(listener: SessionWorkerListener): () => void {
    this.listeners.add(listener);
 
    return () => {
      this.listeners.delete(listener);
 
      // If no more listeners, stop monitoring but keep worker alive
      if (this.listeners.size === 0) {
        this.stopMonitoring();
      }
    };
  }
 
  terminate(): void {
    if (this.worker) {
      this.worker.terminate();
      this.worker = null;
      this.workerId = null;
      this.isMonitoring = false;
      this.listeners.clear();
    }
  }
 
  isActive(): boolean {
    return this.worker !== null;
  }
 
  // Get current worker ID for debugging
  getWorkerId(): string | null {
    return this.workerId;
  }
}
 
export const sessionWorkerManager = SessionWorkerManager.getInstance();