All files / models/cad initializeSectorLoader.ts

91.89% Statements 34/37
75% Branches 6/8
80% Functions 4/5
91.89% Lines 34/37

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        2x                         2x         5x 5x 5x   5x 15x 15x 15x 15x         5x 8x   8x 8x 8x   8x 3x           3x 3x 3x           8x 15x 15x     8x 8x 8x                 8x     5x 22x 7x   15x 15x 15x     5x          
/*!
 * Copyright 2020 Cognite AS
 */
 
import { setUnion, setDifference } from '../../utils/setUtils';
import { DiscardSectorDelegate, ConsumeSectorDelegate, GetSectorDelegate } from './delegates';
 
export interface SectorActivator {
  update: (wantedSectorIds: Set<number>) => boolean;
  refresh: () => boolean;
}
 
interface QueuedSector<T> {
  sectorId: number;
  sector: T;
}
 
export function initializeSectorLoader<T>(
  getSector: GetSectorDelegate<T>,
  discardSector: DiscardSectorDelegate,
  consumeSector: ConsumeSectorDelegate<T>
): SectorActivator {
  const activeSectorIds = new Set<number>();
  const activeSectorRequests = new Map<number, Promise<void>>();
  let consumeQueue: QueuedSector<T>[] = [];
 
  const getConsumeAndDeleteRequest = async (sectorId: number) => {
    const sector = await getSector(sectorId);
    activeSectorRequests.delete(sectorId);
    consumeQueue.push({ sectorId, sector });
    activeSectorIds.add(sectorId);
  };
 
  // TODO 2019-12-17 larsmoa: This function is async but does not return Promise. Consider if
  // this really needs to returnd boolean needsRedraw or if it could return a promise
  const update = (wantedSectorIds: Set<number>) => {
    const start = performance.now();
 
    const activeOrInFlight = setUnion(activeSectorIds, new Set<number>(activeSectorRequests.keys()));
    const newSectorIds = setDifference(wantedSectorIds, activeOrInFlight);
    const discardedSectorIds = setDifference(activeOrInFlight, wantedSectorIds);
 
    for (const id of discardedSectorIds) {
      Iif (activeSectorRequests.has(id)) {
        // Request is in flight
        discardSector(id);
        activeSectorRequests.delete(id);
      } else {
        // Sector processed
        discardSector(id);
        activeSectorIds.delete(id);
        consumeQueue = consumeQueue.filter(({ sectorId }) => {
          return sectorId !== id;
        });
      }
    }
 
    for (const id of newSectorIds) {
      const request = getConsumeAndDeleteRequest(id);
      activeSectorRequests.set(id, request);
    }
 
    const needsRedraw = newSectorIds.size > 0 || discardedSectorIds.size > 0;
    Eif (needsRedraw) {
      console.log(
        `activateSectors() [wanted: ${wantedSectorIds.size} ` +
          `new: ${newSectorIds.size}` +
          ` discarded: ${discardedSectorIds.size}` +
          ` active: ${activeSectorIds.size}` +
          ` in-flight: ${activeSectorRequests.size}] time=${(performance.now() - start).toPrecision(2)} ms`
      );
    }
 
    return needsRedraw;
  };
 
  const refresh = () => {
    if (consumeQueue.length < 1) {
      return false;
    }
    const { sectorId, sector } = consumeQueue.shift()!;
    consumeSector(sectorId, sector);
    return true;
  };
 
  return {
    update,
    refresh
  };
}