Home Manual Reference Source Test

lib/database-change-record-debouncer.js

/**
DatabaseChangeRecordDebouncer.accumulate is a guarded version of trigger that can accumulate changes.
This means that even if you're a bad person and call `persistModel` 100 times
from 100 task objects queued at the same time, it will only create one
`trigger` event. This is important since the database triggering impacts
the entire application.

@private
*/
export default class DatabaseChangeRecordDebouncer {
  constructor({onTrigger, maxTriggerDelay}) {
    this._options = {onTrigger, maxTriggerDelay};
    this._record = null;
  }

  _flushAfterDelay() {
    this._cancelFlush();
    this._flushTimer = setTimeout(() => this._flush(), this._options.maxTriggerDelay);
  }

  _cancelFlush() {
    if (this._flushTimer) {
      clearTimeout(this._flushTimer);
      this._flushTimer = null;
    }
  }

  _flush() {
    if (!this._record) {
      return;
    }

    this._cancelFlush();
    this._options.onTrigger(this._record);
    this._record = null;

    if (this._promiseResolve) {
      this._promiseResolve();
      this._promiseResolve = null;
      this._promise = null;
    }
  }

  accumulate(change) {
    this._promise = this._promise || new Promise((resolve) => {
      this._promiseResolve = resolve;
    });

    if (this._record && this._record.canAppend(change)) {
      this._record.append(change);
    } else {
      this._flush();
      this._record = change;
      this._flushAfterDelay();
    }

    return this._promise;
  }
}