{"version":3,"file":"prefetch-queue.mjs","sources":["../../../../src/lib/performance/prefetch/prefetch-queue.ts"],"sourcesContent":["/**\n * @file Prefetch Queue\n * @description Priority-based prefetch queue with rate limiting, deduplication,\n * and network-aware throttling.\n *\n * Features:\n * - Priority-based scheduling\n * - Rate limiting\n * - Deduplication\n * - Network-aware throttling\n * - Progress tracking\n * - Cancellation support\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Prefetch priority levels\n */\nexport type PrefetchPriority = 'critical' | 'high' | 'normal' | 'low' | 'idle';\n\n/**\n * Prefetch item status\n */\nexport type PrefetchStatus = 'pending' | 'loading' | 'completed' | 'failed' | 'cancelled';\n\n/**\n * Prefetch item\n */\nexport interface PrefetchItem {\n  id: string;\n  url: string;\n  type: 'document' | 'script' | 'style' | 'image' | 'font' | 'fetch';\n  priority: PrefetchPriority;\n  status: PrefetchStatus;\n  createdAt: number;\n  startedAt?: number;\n  completedAt?: number;\n  size?: number;\n  error?: Error;\n  retryCount: number;\n  metadata?: Record<string, unknown>;\n}\n\n/**\n * Queue configuration\n */\nexport interface PrefetchQueueConfig {\n  /** Maximum concurrent prefetches */\n  maxConcurrent: number;\n  /** Maximum queue size */\n  maxQueueSize: number;\n  /** Maximum retry attempts */\n  maxRetries: number;\n  /** Retry delay in ms */\n  retryDelay: number;\n  /** Enable network-aware throttling */\n  networkAware: boolean;\n  /** Concurrent limits by network type */\n  concurrentByNetwork: Record<string, number>;\n  /** Enable deduplication */\n  deduplicate: boolean;\n  /** Time-to-live for completed items in ms */\n  completedTTL: number;\n  /** Enable priority boosting for aged items */\n  priorityBoost: boolean;\n  /** Age threshold for priority boost in ms */\n  boostAgeThreshold: number;\n  /** Debug mode */\n  debug: boolean;\n}\n\n/**\n * Queue statistics\n */\nexport interface QueueStats {\n  pending: number;\n  loading: number;\n  completed: number;\n  failed: number;\n  cancelled: number;\n  totalSize: number;\n  averageLoadTime: number;\n}\n\n/**\n * Queue event types\n */\nexport type QueueEventType = 'enqueue' | 'start' | 'complete' | 'fail' | 'cancel' | 'drain';\n\n/**\n * Queue event listener\n */\nexport type QueueEventListener = (type: QueueEventType, item: PrefetchItem) => void;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: PrefetchQueueConfig = {\n  maxConcurrent: 4,\n  maxQueueSize: 100,\n  maxRetries: 2,\n  retryDelay: 1000,\n  networkAware: true,\n  concurrentByNetwork: {\n    '4g': 4,\n    '3g': 2,\n    '2g': 1,\n    'slow-2g': 1,\n  },\n  deduplicate: true,\n  completedTTL: 60000, // 1 minute\n  priorityBoost: true,\n  boostAgeThreshold: 5000, // 5 seconds\n  debug: false,\n};\n\nconst PRIORITY_VALUES: Record<PrefetchPriority, number> = {\n  critical: 0,\n  high: 1,\n  normal: 2,\n  low: 3,\n  idle: 4,\n};\n\n// ============================================================================\n// Prefetch Queue\n// ============================================================================\n\n/**\n * Priority-based prefetch queue\n */\nexport class PrefetchQueue {\n  private config: PrefetchQueueConfig;\n  private items: Map<string, PrefetchItem> = new Map();\n  private activeCount = 0;\n  private listeners: Set<QueueEventListener> = new Set();\n  private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n  private idCounter = 0;\n  private paused = false;\n\n  constructor(config: Partial<PrefetchQueueConfig> = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n    this.startCleanup();\n  }\n\n  /**\n   * Enqueue a prefetch item\n   */\n  enqueue(\n    url: string,\n    options: {\n      type?: PrefetchItem['type'];\n      priority?: PrefetchPriority;\n      metadata?: Record<string, unknown>;\n    } = {}\n  ): string | null {\n    // Check deduplication\n    if (this.config.deduplicate) {\n      const existing = this.findByUrl(url);\n      if (existing && existing.status !== 'failed') {\n        this.log(`Skipping duplicate URL: ${url}`);\n        return existing.id;\n      }\n    }\n\n    // Check queue size\n    if (this.getPendingCount() >= this.config.maxQueueSize) {\n      this.log(`Queue full, dropping: ${url}`);\n      return null;\n    }\n\n    const id = this.generateId();\n    const item: PrefetchItem = {\n      id,\n      url,\n      type: options.type ?? 'document',\n      priority: options.priority ?? 'normal',\n      status: 'pending',\n      createdAt: Date.now(),\n      retryCount: 0,\n      metadata: options.metadata,\n    };\n\n    this.items.set(id, item);\n    this.log(`Enqueued: ${url} (priority: ${item.priority})`);\n    this.notifyListeners('enqueue', item);\n\n    // Process queue\n    this.processQueue();\n\n    return id;\n  }\n\n  /**\n   * Enqueue multiple items\n   */\n  enqueueMany(\n    items: Array<{\n      url: string;\n      type?: PrefetchItem['type'];\n      priority?: PrefetchPriority;\n      metadata?: Record<string, unknown>;\n    }>\n  ): string[] {\n    const ids: string[] = [];\n\n    for (const item of items) {\n      const id = this.enqueue(item.url, item);\n      if (id !== null) {\n        ids.push(id);\n      }\n    }\n\n    return ids;\n  }\n\n  /**\n   * Cancel a prefetch item\n   */\n  cancel(id: string): boolean {\n    const item = this.items.get(id);\n    if (item == null || item.status === 'completed' || item.status === 'cancelled') {\n      return false;\n    }\n\n    const wasLoading = item.status === 'loading';\n    item.status = 'cancelled';\n    item.completedAt = Date.now();\n\n    if (wasLoading) {\n      this.activeCount--;\n    }\n\n    this.log(`Cancelled: ${item.url}`);\n    this.notifyListeners('cancel', item);\n\n    return true;\n  }\n\n  /**\n   * Cancel all pending items\n   */\n  cancelAll(): number {\n    let cancelled = 0;\n\n    for (const item of this.items.values()) {\n      if (item.status === 'pending') {\n        item.status = 'cancelled';\n        item.completedAt = Date.now();\n        cancelled++;\n        this.notifyListeners('cancel', item);\n      }\n    }\n\n    this.log(`Cancelled ${cancelled} items`);\n    return cancelled;\n  }\n\n  /**\n   * Pause the queue\n   */\n  pause(): void {\n    this.paused = true;\n    this.log('Queue paused');\n  }\n\n  /**\n   * Resume the queue\n   */\n  resume(): void {\n    this.paused = false;\n    this.log('Queue resumed');\n    this.processQueue();\n  }\n\n  /**\n   * Check if paused\n   */\n  isPaused(): boolean {\n    return this.paused;\n  }\n\n  /**\n   * Get item by ID\n   */\n  getItem(id: string): PrefetchItem | undefined {\n    return this.items.get(id);\n  }\n\n  /**\n   * Get item by URL\n   */\n  findByUrl(url: string): PrefetchItem | undefined {\n    for (const item of this.items.values()) {\n      if (item.url === url) {\n        return item;\n      }\n    }\n    return undefined;\n  }\n\n  /**\n   * Check if URL is queued or completed\n   */\n  has(url: string): boolean {\n    const item = this.findByUrl(url);\n    return item !== undefined && item.status !== 'cancelled';\n  }\n\n  /**\n   * Check if URL was successfully prefetched\n   */\n  isPrefetched(url: string): boolean {\n    const item = this.findByUrl(url);\n    return item?.status === 'completed';\n  }\n\n  /**\n   * Get queue statistics\n   */\n  getStats(): QueueStats {\n    let pending = 0;\n    let loading = 0;\n    let completed = 0;\n    let failed = 0;\n    let cancelled = 0;\n    let totalSize = 0;\n    const loadTimes: number[] = [];\n\n    for (const item of this.items.values()) {\n      switch (item.status) {\n        case 'pending':\n          pending++;\n          break;\n        case 'loading':\n          loading++;\n          break;\n        case 'completed':\n          completed++;\n          if (item.size !== undefined) totalSize += item.size;\n          if (item.startedAt !== undefined && item.completedAt !== undefined) {\n            loadTimes.push(item.completedAt - item.startedAt);\n          }\n          break;\n        case 'failed':\n          failed++;\n          break;\n        case 'cancelled':\n          cancelled++;\n          break;\n      }\n    }\n\n    return {\n      pending,\n      loading,\n      completed,\n      failed,\n      cancelled,\n      totalSize,\n      averageLoadTime:\n        loadTimes.length > 0 ? loadTimes.reduce((a, b) => a + b, 0) / loadTimes.length : 0,\n    };\n  }\n\n  /**\n   * Subscribe to queue events\n   */\n  subscribe(listener: QueueEventListener): () => void {\n    this.listeners.add(listener);\n    return () => this.listeners.delete(listener);\n  }\n\n  /**\n   * Clear the queue\n   */\n  clear(): void {\n    this.cancelAll();\n    this.items.clear();\n    this.activeCount = 0;\n    this.log('Queue cleared');\n  }\n\n  /**\n   * Destroy the queue\n   */\n  destroy(): void {\n    this.clear();\n    if (this.cleanupTimer !== null) {\n      clearInterval(this.cleanupTimer);\n      this.cleanupTimer = null;\n    }\n  }\n\n  // ============================================================================\n  // Private Methods\n  // ============================================================================\n\n  private processQueue(): void {\n    if (this.paused) {\n      return;\n    }\n\n    const maxConcurrent = this.getMaxConcurrent();\n\n    while (this.activeCount < maxConcurrent) {\n      const next = this.getNextItem();\n      if (next === null) {\n        break;\n      }\n\n      void this.executeItem(next);\n    }\n\n    // Check if queue is empty\n    if (this.getPendingCount() === 0 && this.activeCount === 0) {\n      const dummyItem: PrefetchItem = {\n        id: 'drain',\n        url: '',\n        type: 'document',\n        priority: 'normal',\n        status: 'completed',\n        createdAt: Date.now(),\n        retryCount: 0,\n      };\n      this.notifyListeners('drain', dummyItem);\n    }\n  }\n\n  private getNextItem(): PrefetchItem | null {\n    const pending = Array.from(this.items.values())\n      .filter((item) => item.status === 'pending')\n      .sort((a, b) => this.compareItems(a, b));\n\n    return pending[0] ?? null;\n  }\n\n  private compareItems(a: PrefetchItem, b: PrefetchItem): number {\n    // Apply priority boost for aged items\n    let priorityA = PRIORITY_VALUES[a.priority];\n    let priorityB = PRIORITY_VALUES[b.priority];\n\n    if (this.config.priorityBoost) {\n      const now = Date.now();\n      if (now - a.createdAt > this.config.boostAgeThreshold) {\n        priorityA = Math.max(0, priorityA - 1);\n      }\n      if (now - b.createdAt > this.config.boostAgeThreshold) {\n        priorityB = Math.max(0, priorityB - 1);\n      }\n    }\n\n    // Compare by boosted priority\n    if (priorityA !== priorityB) {\n      return priorityA - priorityB;\n    }\n\n    // Then by creation time (older first)\n    return a.createdAt - b.createdAt;\n  }\n\n  private async executeItem(item: PrefetchItem): Promise<void> {\n    item.status = 'loading';\n    item.startedAt = Date.now();\n    this.activeCount++;\n\n    this.log(`Starting prefetch: ${item.url}`);\n    this.notifyListeners('start', item);\n\n    try {\n      await this.prefetch(item);\n\n      item.status = 'completed';\n      item.completedAt = Date.now();\n\n      this.log(`Completed prefetch: ${item.url} (${item.completedAt - (item.startedAt ?? 0)}ms)`);\n      this.notifyListeners('complete', item);\n    } catch (error) {\n      item.error = error instanceof Error ? error : new Error(String(error));\n      item.retryCount++;\n\n      if (item.retryCount <= this.config.maxRetries) {\n        this.log(`Retrying prefetch: ${item.url} (attempt ${item.retryCount})`);\n        item.status = 'pending';\n\n        // Schedule retry\n        setTimeout(() => {\n          this.processQueue();\n        }, this.config.retryDelay * item.retryCount);\n      } else {\n        item.status = 'failed';\n        item.completedAt = Date.now();\n\n        this.log(`Failed prefetch: ${item.url}`, item.error);\n        this.notifyListeners('fail', item);\n      }\n    } finally {\n      this.activeCount--;\n      this.processQueue();\n    }\n  }\n\n  private async prefetch(item: PrefetchItem): Promise<void> {\n    switch (item.type) {\n      case 'document':\n        await this.prefetchDocument(item);\n        break;\n      case 'script':\n        await this.prefetchScript(item);\n        break;\n      case 'style':\n        await this.prefetchStyle(item);\n        break;\n      case 'image':\n        await this.prefetchImage(item);\n        break;\n      case 'font':\n        await this.prefetchFont(item);\n        break;\n      case 'fetch':\n        await this.prefetchFetch(item);\n        break;\n    }\n  }\n\n  private async prefetchDocument(item: PrefetchItem): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const link = document.createElement('link');\n      link.rel = 'prefetch';\n      link.href = item.url;\n      link.as = 'document';\n\n      link.onload = () => resolve();\n      link.onerror = () => reject(new Error(`Failed to prefetch: ${item.url}`));\n\n      document.head.appendChild(link);\n    });\n  }\n\n  private async prefetchScript(item: PrefetchItem): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const link = document.createElement('link');\n      link.rel = 'prefetch';\n      link.href = item.url;\n      link.as = 'script';\n\n      link.onload = () => resolve();\n      link.onerror = () => reject(new Error(`Failed to prefetch: ${item.url}`));\n\n      document.head.appendChild(link);\n    });\n  }\n\n  private async prefetchStyle(item: PrefetchItem): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const link = document.createElement('link');\n      link.rel = 'prefetch';\n      link.href = item.url;\n      link.as = 'style';\n\n      link.onload = () => resolve();\n      link.onerror = () => reject(new Error(`Failed to prefetch: ${item.url}`));\n\n      document.head.appendChild(link);\n    });\n  }\n\n  private async prefetchImage(item: PrefetchItem): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const img = new Image();\n      img.onload = () => {\n        item.size = img.naturalWidth * img.naturalHeight * 4; // Rough estimate\n        resolve();\n      };\n      img.onerror = () => reject(new Error(`Failed to prefetch: ${item.url}`));\n      img.src = item.url;\n    });\n  }\n\n  private async prefetchFont(item: PrefetchItem): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const link = document.createElement('link');\n      link.rel = 'prefetch';\n      link.href = item.url;\n      link.as = 'font';\n      link.crossOrigin = 'anonymous';\n\n      link.onload = () => resolve();\n      link.onerror = () => reject(new Error(`Failed to prefetch: ${item.url}`));\n\n      document.head.appendChild(link);\n    });\n  }\n\n  private async prefetchFetch(item: PrefetchItem): Promise<void> {\n    const response = await fetch(item.url, {\n      method: 'GET',\n      credentials: 'same-origin',\n    });\n\n    if (!response.ok) {\n      throw new Error(`HTTP ${response.status}`);\n    }\n\n    // Read body to trigger caching\n    const blob = await response.blob();\n    item.size = blob.size;\n  }\n\n  private getMaxConcurrent(): number {\n    if (!this.config.networkAware) {\n      return this.config.maxConcurrent;\n    }\n\n    const connection = this.getNetworkInfo();\n    if (connection?.effectiveType === undefined) {\n      return this.config.maxConcurrent;\n    }\n\n    return this.config.concurrentByNetwork[connection.effectiveType] ?? this.config.maxConcurrent;\n  }\n\n  private getNetworkInfo(): { effectiveType?: string } | null {\n    const nav = navigator as Navigator & {\n      connection?: { effectiveType?: string };\n    };\n    return nav.connection ?? null;\n  }\n\n  private getPendingCount(): number {\n    let count = 0;\n    for (const item of this.items.values()) {\n      if (item.status === 'pending') {\n        count++;\n      }\n    }\n    return count;\n  }\n\n  private startCleanup(): void {\n    this.cleanupTimer = setInterval(() => {\n      this.cleanup();\n    }, this.config.completedTTL);\n  }\n\n  private cleanup(): void {\n    const now = Date.now();\n    const toDelete: string[] = [];\n\n    for (const [id, item] of this.items.entries()) {\n      if (\n        (item.status === 'completed' || item.status === 'cancelled') &&\n        item.completedAt != null &&\n        now - item.completedAt > this.config.completedTTL\n      ) {\n        toDelete.push(id);\n      }\n    }\n\n    for (const id of toDelete) {\n      this.items.delete(id);\n    }\n\n    if (toDelete.length > 0) {\n      this.log(`Cleaned up ${toDelete.length} old items`);\n    }\n  }\n\n  private notifyListeners(type: QueueEventType, item: PrefetchItem): void {\n    this.listeners.forEach((listener) => listener(type, item));\n  }\n\n  private generateId(): string {\n    return `prefetch-${Date.now()}-${++this.idCounter}`;\n  }\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[PrefetchQueue] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet queueInstance: PrefetchQueue | null = null;\n\n/**\n * Get or create the global prefetch queue\n */\nexport function getPrefetchQueue(config?: Partial<PrefetchQueueConfig>): PrefetchQueue {\n  queueInstance ??= new PrefetchQueue(config);\n  return queueInstance;\n}\n\n/**\n * Reset the queue instance\n */\nexport function resetPrefetchQueue(): void {\n  if (queueInstance !== null) {\n    queueInstance.destroy();\n    queueInstance = null;\n  }\n}\n"],"names":["DEFAULT_CONFIG","PRIORITY_VALUES","PrefetchQueue","config","url","options","existing","id","item","items","ids","wasLoading","cancelled","pending","loading","completed","failed","totalSize","loadTimes","a","b","listener","maxConcurrent","next","dummyItem","priorityA","priorityB","now","error","resolve","reject","link","img","response","blob","connection","count","toDelete","type","message","args","queueInstance","getPrefetchQueue","resetPrefetchQueue"],"mappings":"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"}