function makeInterruptableAsyncInterval(fn, options) {
  let timerId;
  let lastCallTime;
  let lastWakeTime;
  let stopped = false;

  options = options || {};
  const interval = options.interval || 1000;
  const minInterval = options.minInterval || 500;
  const immediate = typeof options.immediate === 'boolean' ? options.immediate : false;
  const clock = typeof options.clock === 'function' ? options.clock : now;

  function wake() {
    const currentTime = clock();
    const timeSinceLastWake = currentTime - lastWakeTime;
    const timeSinceLastCall = currentTime - lastCallTime;
    const timeUntilNextCall = interval - timeSinceLastCall;
    lastWakeTime = currentTime;

    // For the streaming protocol: there is nothing obviously stopping this
    // interval from being woken up again while we are waiting "infinitely"
    // for `fn` to be called again`. Since the function effectively
    // never completes, the `timeUntilNextCall` will continue to grow
    // negatively unbounded, so it will never trigger a reschedule here.

    // debounce multiple calls to wake within the `minInterval`
    if (timeSinceLastWake < minInterval) {
      return;
    }

    // reschedule a call as soon as possible, ensuring the call never happens
    // faster than the `minInterval`
    if (timeUntilNextCall > minInterval) {
      reschedule(minInterval);
    }

    // This is possible in virtualized environments like AWS Lambda where our
    // clock is unreliable. In these cases the timer is "running" but never
    // actually completes, so we want to execute immediately and then attempt
    // to reschedule.
    if (timeUntilNextCall < 0) {
      executeAndReschedule();
    }
  }

  function stop() {
    stopped = true;
    if (timerId) {
      clearTimeout(timerId);
      timerId = null;
    }

    lastCallTime = 0;
    lastWakeTime = 0;
  }

  function reschedule(ms) {
    if (stopped) return;
    clearTimeout(timerId);
    timerId = setTimeout(executeAndReschedule, ms || interval);
  }

  function executeAndReschedule() {
    lastWakeTime = 0;
    lastCallTime = clock();

    fn(err => {
      if (err) throw err;
      reschedule(interval);
    });
  }

  if (immediate) {
    executeAndReschedule();
  } else {
    lastCallTime = clock();
    reschedule();
  }

  return { wake, stop };
}
/**
 * Creates an interval timer which is able to be woken up sooner than
 * the interval. The timer will also debounce multiple calls to wake
 * ensuring that the function is only ever called once within a minimum
 * interval window.
 *
 * @param {function} fn An async function to run on an interval, must accept a `callback` as its only parameter
 * @param {object} [options] Optional settings
 * @param {number} [options.interval] The interval at which to run the provided function
 * @param {number} [options.minInterval] The minimum time which must pass between invocations of the provided function
 * @param {boolean} [options.immediate] Execute the function immediately when the interval is started
 */
Creates an interval timer which is able to be woken up sooner than
the interval. The timer will also debounce multiple calls to wake
ensuring that the function is only ever called once within a minimum
interval window.


Creates an interval timer which is able to be woken up sooner than the interval . The timer will also debounce multiple calls to wake ensuring that the function is only ever called once within a minimum interval window .
function makeInterruptableAsyncInterval(fn, options) {
  let timerId;
  let lastCallTime;
  let lastWakeTime;
  let stopped = false;
  options = options || {};
  const interval = options.interval || 1000;
  const minInterval = options.minInterval || 500;
  const immediate = typeof options.immediate === 'boolean' ? options.immediate : false;
  const clock = typeof options.clock === 'function' ? options.clock : now;
  function wake() {
    const currentTime = clock();
    const timeSinceLastWake = currentTime - lastWakeTime;
    const timeSinceLastCall = currentTime - lastCallTime;
    const timeUntilNextCall = interval - timeSinceLastCall;
    lastWakeTime = currentTime;
    if (timeSinceLastWake < minInterval) {
      return;
    }
    if (timeUntilNextCall > minInterval) {
      reschedule(minInterval);
    }
    if (timeUntilNextCall < 0) {
      executeAndReschedule();
    }
  }
  function stop() {
    stopped = true;
    if (timerId) {
      clearTimeout(timerId);
      timerId = null;
    }
    lastCallTime = 0;
    lastWakeTime = 0;
  }
  function reschedule(ms) {
    if (stopped) return;
    clearTimeout(timerId);
    timerId = setTimeout(executeAndReschedule, ms || interval);
  }
  function executeAndReschedule() {
    lastWakeTime = 0;
    lastCallTime = clock();
    fn(err => {
      if (err) throw err;
      reschedule(interval);
    });
  }
  if (immediate) {
    executeAndReschedule();
  } else {
    lastCallTime = clock();
    reschedule();
  }
  return { wake, stop };
}
function makeInterruptableAsyncInterval ( fn , options ) { let timerId ; let lastCallTime ; let lastWakeTime ; let stopped = false ; options = options || { } ; const interval = options . interval || 1000 ; const minInterval = options . minInterval || 500 ; const immediate = typeof options . immediate === 'boolean' ? options . immediate : false ; const clock = typeof options . clock === 'function' ? options . clock : now ; function wake ( ) { const currentTime = clock ( ) ; const timeSinceLastWake = currentTime - lastWakeTime ; const timeSinceLastCall = currentTime - lastCallTime ; const timeUntilNextCall = interval - timeSinceLastCall ; lastWakeTime = currentTime ; if ( timeSinceLastWake < minInterval ) { return ; } if ( timeUntilNextCall > minInterval ) { reschedule ( minInterval ) ; } if ( timeUntilNextCall < 0 ) { executeAndReschedule ( ) ; } } function stop ( ) { stopped = true ; if ( timerId ) { clearTimeout ( timerId ) ; timerId = null ; } lastCallTime = 0 ; lastWakeTime = 0 ; } function reschedule ( ms ) { if ( stopped ) return ; clearTimeout ( timerId ) ; timerId = setTimeout ( executeAndReschedule , ms || interval ) ; } function executeAndReschedule ( ) { lastWakeTime = 0 ; lastCallTime = clock ( ) ; fn ( err => { if ( err ) throw err ; reschedule ( interval ) ; } ) ; } if ( immediate ) { executeAndReschedule ( ) ; } else { lastCallTime = clock ( ) ; reschedule ( ) ; } return { wake , stop } ; }
Creates an interval timer which is able to be woken up sooner than
 the interval.
Creates an interval timer which is able to be woken up sooner than the interval .
// For the streaming protocol: there is nothing obviously stopping this // interval from being woken up again while we are waiting "infinitely" // for `fn` to be called again`. Since the function effectively // never completes, the `timeUntilNextCall` will continue to grow // negatively unbounded, so it will never trigger a reschedule here. // debounce multiple calls to wake within the `minInterval` // reschedule a call as soon as possible, ensuring the call never happens // faster than the `minInterval` // This is possible in virtualized environments like AWS Lambda where our // clock is unreliable. In these cases the timer is "running" but never // actually completes, so we want to execute immediately and then attempt // to reschedule.