All files TimedState.ts

96.66% Statements 29/30
100% Branches 8/8
80% Functions 4/5
96.66% Lines 29/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61  1x 1x             10x 10x       10x       10x       10x 10x 10x 10x     26x 26x 26x 3x 3x   23x 14x 5x         15x 15x 15x 15x 14x 15x 14x 14x 14x             15x     1x  
/**
 * TimedState works similar to TimedQueue, but instead of saving
 * a list of all items pushed, it reduces the state on each push.
 */
export class TimedState<S, I> {
  /**
   * State will be flushed when it reaches this number of items.
   */
  public itemLimit: number = 100;
 
  /**
   * State will be flushed after this many milliseconds.
   */
  public timeLimit: number = 5_000;
 
  /**
   * Method that will be called when state is flushed.
   */
  public onFlush: (state: S) => void = () => {};
 
  constructor(
    protected readonly initState: () => S,
    protected readonly reducer: (state: S, item: I) => S,
  ) {}
 
  protected length: number = 0;
  protected state: S = this.initState();
  private timer: any = null;
 
  push(item: I): void {
    this.length++;
    this.state = this.reducer(this.state, item);
    if (this.length >= this.itemLimit) {
      this.flush();
      return;
    }
    if (!this.timer) {
      this.timer = setTimeout(() => {
        this.flush();
      }, this.timeLimit);
    }
  }
 
  flush(): S {
    const {state, length} = this;
    this.state = this.initState();
    this.length = 0;
    if (this.timer) clearTimeout(this.timer);
    if (length) {
      this.timer = null;
      try {
        this.onFlush(state);
      } catch (error) {
        // tslint:disable-next-line
        console.error('TimedState', error);
      }
    }
    return state;
  }
}