All files / src lossy.ts

94.11% Statements 16/17
80% Branches 4/5
100% Functions 4/4
100% Lines 15/15

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        4x       4x       4x                 5x   5x 11x     11x         11x   11x   11x 11x       14x 1x     14x   12x        
// We have the lossless transformation of the delta stream.
// We want to enable transformations from the lossless view, 
// into various possible "lossy" views that combine or exclude some information.
 
import Debug from 'debug';
import {DeltaFilter, DeltaID} from "./delta";
import {Lossless, LosslessViewOne} from "./lossless";
import {DomainEntityID} from "./types";
const debug = Debug('rz:lossy');
 
// The lossy model will subscribe to events from the lossless model,
// and perform incremental updates using its reducer function.
export abstract class Lossy<Accumulator, Result> {
  deltaFilter?: DeltaFilter;
  accumulator?: Accumulator;
 
  abstract initializer(v: LosslessViewOne): Accumulator;
  abstract reducer(acc: Accumulator, cur: LosslessViewOne): Accumulator;
  abstract resolver(cur: Accumulator): Result;
 
  constructor(
    readonly lossless: Lossless,
  ) {
    this.lossless.eventStream.on("updated", (id, deltaIds) => {
      debug(`[${this.lossless.rhizomeNode.config.peerId}] entity ${id} updated, deltaIds:`,
        JSON.stringify(deltaIds));
 
      this.ingestUpdate(id, deltaIds);
    });
  }
 
  private ingestUpdate(id: DomainEntityID, deltaIds: DeltaID[]) {
    const losslessPartial = this.lossless.viewSpecific(id, deltaIds, this.deltaFilter);
 
    Iif (!losslessPartial) return;
 
    const latest = this.accumulator || this.initializer(losslessPartial);
    this.accumulator = this.reducer(latest, losslessPartial);
  }
 
  public resolve(entityIds?: DomainEntityID[]): Result | undefined {
    if (!entityIds) {
      entityIds = Array.from(this.lossless.domainEntities.keys());
    }
 
    if (!this.accumulator) return undefined;
 
    return this.resolver(this.accumulator);
  }
}