| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 | import { SentryError } from './error.js';import { rejectedSyncPromise, SyncPromise, resolvedSyncPromise } from './syncpromise.js';/** * Creates an new PromiseBuffer object with the specified limit * @param limit max number of promises that can be stored in the buffer */function makePromiseBuffer(limit) {  const buffer = [];  function isReady() {    return limit === undefined || buffer.length < limit;  }  /**   * Remove a promise from the queue.   *   * @param task Can be any PromiseLike<T>   * @returns Removed promise.   */  function remove(task) {    return buffer.splice(buffer.indexOf(task), 1)[0];  }  /**   * Add a promise (representing an in-flight action) to the queue, and set it to remove itself on fulfillment.   *   * @param taskProducer A function producing any PromiseLike<T>; In previous versions this used to be `task:   *        PromiseLike<T>`, but under that model, Promises were instantly created on the call-site and their executor   *        functions therefore ran immediately. Thus, even if the buffer was full, the action still happened. By   *        requiring the promise to be wrapped in a function, we can defer promise creation until after the buffer   *        limit check.   * @returns The original promise.   */  function add(taskProducer) {    if (!isReady()) {      return rejectedSyncPromise(new SentryError('Not adding Promise because buffer limit was reached.'));    }    // start the task and add its promise to the queue    const task = taskProducer();    if (buffer.indexOf(task) === -1) {      buffer.push(task);    }    void task      .then(() => remove(task))      // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`      // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't      // have promises, so TS has to polyfill when down-compiling.)      .then(null, () =>        remove(task).then(null, () => {          // We have to add another catch here because `remove()` starts a new promise chain.        }),      );    return task;  }  /**   * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.   *   * @param timeout The time, in ms, after which to resolve to `false` if the queue is still non-empty. Passing `0` (or   * not passing anything) will make the promise wait as long as it takes for the queue to drain before resolving to   * `true`.   * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and   * `false` otherwise   */  function drain(timeout) {    return new SyncPromise((resolve, reject) => {      let counter = buffer.length;      if (!counter) {        return resolve(true);      }      // wait for `timeout` ms and then resolve to `false` (if not cancelled first)      const capturedSetTimeout = setTimeout(() => {        if (timeout && timeout > 0) {          resolve(false);        }      }, timeout);      // if all promises resolve in time, cancel the timer and resolve to `true`      buffer.forEach(item => {        void resolvedSyncPromise(item).then(() => {          if (!--counter) {            clearTimeout(capturedSetTimeout);            resolve(true);          }        }, reject);      });    });  }  return {    $: buffer,    add,    drain,  };}export { makePromiseBuffer };//# sourceMappingURL=promisebuffer.js.map
 |