All files / services/cache cache-layer.ts

48.72% Statements 19/39
33.33% Branches 2/6
35% Functions 7/20
54.29% Lines 19/35

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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87  1x 1x   1x   3x     3x     2x       3x 3x 3x       3x                   2x                           2x 2x 2x 2x 2x 2x                                   1x   1x                              
import { CacheLayerInterface, CacheServiceConfigInterface } from './cache-layer.interfaces';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { filter, map } from 'rxjs/operators';
 
export class CacheLayer<T> {
 
  public items: BehaviorSubject<Array<T>> = new BehaviorSubject([]);
  public name: string;
  public config: CacheServiceConfigInterface;
  public map: Map<any, any> = new Map();
 
  public get(name): T {
    return this.map.get(name);
  }
 
  constructor(layer: CacheLayerInterface) {
    this.name = layer.name;
    this.config = layer.config;
    this.initHook(layer);
  }
 
  private initHook(layer) {
    Iif (this.config.maxAge) {
      this.onExpireAll(layer);
    }
  }
 
  private onExpireAll(layer) {
    layer.items.forEach(item => this.onExpire(item['key']));
  }
 
  private putItemHook(layerItem): void {
    Iif (this.config.maxAge) {
      this.onExpire(layerItem['key']);
    }
  }
 
  public getItem(key: string): T {
    if (this.map.has(key)) {
      return this.get(key);
    } else {
      return null;
    }
  }
 
  public putItem(layerItem: T): T {
    this.map.set(layerItem['key'], layerItem);
    const item = this.get(layerItem['key']);
    const filteredItems = this.items.getValue().filter(item => item['key'] !== layerItem['key']);
    this.items.next([...filteredItems, item]);
    this.putItemHook(layerItem);
    return layerItem;
  }
 
  private onExpire(key: string): void {
    Observable
      .create(observer => observer.next())
      .timeoutWith(this.config.maxAge, of(1))
      .skip(1)
      .subscribe(() => this.removeItem(key));
  }
 
  public removeItem(key: string): void {
    const newLayerItems = this.items.getValue().filter(item => item['key'] !== key);
    this.map.delete(key);
    this.items.next(newLayerItems);
  }
 
  public getItemObservable(key: string): Observable<T> {
    return this.items.asObservable()
      .pipe(
        filter(() => !!this.map.has(key)),
        map(() => this.map.get(key))
      );
  }
 
  public flushCache(): Observable<boolean> {
    return this.items.asObservable()
      .pipe(
        map(items => {
          items.forEach(i => this.removeItem(i['key']));
          return true;
        })
      );
  }
 
}