{"version":3,"file":"atomic-sync-queue.mjs","sourceRoot":"","sources":["../../../src/backup-and-sync/service/atomic-sync-queue.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,qBAAqB,EAAE,wBAAwB;AAExD,OAAO,EAAE,mBAAmB,EAAE,yBAAqB;AAGnD;;;GAGG;AACH,MAAM,OAAO,eAAe;IAA5B;QACE;;WAEG;QACM,iCAA4B,EAAE,EAAC;QAExC;;WAEG;QACH,kDAA0B,KAAK,EAAC;IAmGlC,CAAC;IAjGC;;;;;OAKG;IACH,eAAe,CAAC,YAAiC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,YAAiC;QACvC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,qBAAqB,EAAE,CAAC;QAE7D,8CAA8C;QAC9C,MAAM,SAAS,GAAoB;YACjC,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,IAAI,CAAC;oBACH,MAAM,YAAY,EAAE,CAAC;oBACrB,OAAO,EAAE,EAAE,CAAC;gBACd,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC;SACF,CAAC;QAEF,oCAAoC;QACpC,uBAAA,IAAI,8BAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC7B,mBAAmB,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YACpE,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,CAAC,CAAC,CAAC;QAEN,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,uBAAA,IAAI,+CAAwB,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,IAAI,uBAAA,IAAI,8BAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,uBAAA,IAAI,2CAA2B,IAAI,MAAA,CAAC;QAEpC,IAAI,CAAC;YACH,OAAO,uBAAA,IAAI,8BAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,uBAAA,IAAI,8BAAO,CAAC,KAAK,EAAE,CAAC;gBAClC,0BAA0B;gBAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM;gBACR,CAAC;gBAED,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,uBAAA,IAAI,2CAA2B,KAAK,MAAA,CAAC;QACvC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,uBAAA,IAAI,8BAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,uBAAA,IAAI,8BAAO,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,IAAI,YAAY;QACd,OAAO,uBAAA,IAAI,+CAAwB,CAAC;IACtC,CAAC;CACF","sourcesContent":["import { createDeferredPromise } from '@metamask/utils';\n\nimport { backupAndSyncLogger } from '../../logger';\nimport type { AtomicSyncEvent } from '../types';\n\n/**\n * Manages atomic sync operations in a queue to prevent concurrent execution\n * and ensure proper ordering of sync events.\n */\nexport class AtomicSyncQueue {\n  /**\n   * Queue for atomic sync events that need to be processed asynchronously.\n   */\n  readonly #queue: AtomicSyncEvent[] = [];\n\n  /**\n   * Flag to prevent multiple queue processing operations from running concurrently.\n   */\n  #isProcessingInProgress = false;\n\n  /**\n   * Clears the queue and enqueues a new sync function.\n   *\n   * @param syncFunction - The sync function to enqueue.\n   * @returns A Promise that resolves when the sync function completes.\n   */\n  clearAndEnqueue(syncFunction: () => Promise<void>): Promise<void> {\n    this.clear();\n    return this.enqueue(syncFunction);\n  }\n\n  /**\n   * Enqueues an atomic sync function for processing.\n   *\n   * @param syncFunction - The sync function to enqueue.\n   * @returns A Promise that resolves when the sync function completes.\n   */\n  enqueue(syncFunction: () => Promise<void>): Promise<void> {\n    const { promise, resolve, reject } = createDeferredPromise();\n\n    // Create the sync event with promise handlers\n    const syncEvent: AtomicSyncEvent = {\n      execute: async () => {\n        try {\n          await syncFunction();\n          resolve?.();\n        } catch (error) {\n          reject?.(error);\n        }\n      },\n    };\n\n    // Add to queue and start processing\n    this.#queue.push(syncEvent);\n    setTimeout(() => {\n      this.process().catch((error) => {\n        backupAndSyncLogger('Error processing atomic sync queue:', error);\n      });\n    }, 0);\n\n    return promise;\n  }\n\n  /**\n   * Processes the atomic sync queue.\n   */\n  async process(): Promise<void> {\n    if (this.#isProcessingInProgress) {\n      return;\n    }\n\n    if (this.#queue.length === 0) {\n      return;\n    }\n\n    this.#isProcessingInProgress = true;\n\n    try {\n      while (this.#queue.length > 0) {\n        const event = this.#queue.shift();\n        /* istanbul ignore next */\n        if (!event) {\n          break;\n        }\n\n        await event.execute();\n      }\n    } finally {\n      this.#isProcessingInProgress = false;\n    }\n  }\n\n  /**\n   * Clears all pending sync events from the queue.\n   * Useful when big sync starts to prevent stale updates.\n   */\n  clear(): void {\n    this.#queue.length = 0;\n  }\n\n  /**\n   * Gets the current queue size.\n   *\n   * @returns The number of pending sync events.\n   */\n  get size(): number {\n    return this.#queue.length;\n  }\n\n  /**\n   * Checks if queue processing is currently in progress.\n   *\n   * @returns True if processing is in progress.\n   */\n  get isProcessing(): boolean {\n    return this.#isProcessingInProgress;\n  }\n}\n"]}