All files / src/modules/cache InMemCache.ts

100% Statements 34/34
75% Branches 9/12
100% Functions 13/13
100% Lines 34/34

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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                                                  2x 2x 2x 2x 2x 2x       2x       1x       1x       120x       2x       1x             9x       1x       8x   8x 1x 1x   8x       2x 2x 2x       2x 2x   2x       2x 2x   2x 2x 2x 2x 1x 1x   2x      
import { clearInterval } from 'timers';
import { CoreCache, type IEntity } from '../../classes';
import type { ICoreKernelModule } from '../../lib';
 
/**
 * In-memory cache implementation that extends {@link CoreCache}.
 *
 * This cache stores simple key/value pairs as well as entity objects indexed
 * by their class name and unique identifier.  It optionally clears all
 * cached data at a configurable interval via {@link #start} and
 * {@link #stop}.
 */
export default class InMemCache extends CoreCache {
  keyMap: Map<string, string>;
 
  eMap: Map<string, Map<string, any>>;
 
  loop: ReturnType<typeof setInterval> | null;
 
  deleteTime?: number;
 
  constructor(
    module: ICoreKernelModule<any, any, any, any, any>,
    deleteTime?: number,
  ) {
    super(`inMemCache`, module);
    this.keyMap = new Map<string, string>();
    this.eMap = new Map<string, Map<string, any>>();
    this.loop = null;
    this.deleteTime = deleteTime;
    this.flash = this.flash.bind(this);
  }
 
  async clearAll(): Promise<void> {
    this.keyMap.clear();
  }
 
  async clearAllE(className: string): Promise<void> {
    this.eMap.get(className)?.clear();
  }
 
  async delete(key: string): Promise<void> {
    this.keyMap.delete(key);
  }
 
  async deleteE(className: string, e_id: string): Promise<boolean> {
    return this.eMap.get(className)?.delete(e_id) || true;
  }
 
  async exist(key: string): Promise<boolean> {
    return this.keyMap.has(key);
  }
 
  async get(key: string): Promise<string | null> {
    return this.keyMap.get(key) ?? null;
  }
 
  async getE<E extends IEntity>(
    className: string,
    e_id: string,
  ): Promise<E | null> {
    return this.eMap.get(className)?.get(e_id);
  }
 
  async set(key: string, val: string): Promise<void> {
    this.keyMap.set(key, val);
  }
 
  async setE<E extends IEntity>(className: string, val: E): Promise<void> {
    let cur = this.eMap.get(className);
 
    if (!cur) {
      cur = new Map<string, any>();
      this.eMap.set(className, cur);
    }
    cur.set(val.e_id, val);
  }
 
  flash() {
    this.debug(`Clear cache:${this.channel}`);
    this.keyMap.clear();
    this.eMap.clear();
  }
 
  async start(): Promise<void> {
    Eif (this.deleteTime) {
      this.loop = setInterval(this.flash, this.deleteTime);
    }
    this.debug(`Init cache:${this.channel}`);
  }
 
  async stop(): Promise<void> {
    Eif (this.loop) {
      clearInterval(this.loop);
    }
    await this.clearAll();
    const iter = this.eMap.keys();
    let key = iter.next();
    while (!key.done || key.value !== undefined) {
      await this.clearAllE(key.value);
      key = iter.next();
    }
    this.flash();
  }
}