CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
toad-cache.cjs879 linesDownload Raw Back to dist
1/**2 * toad-cache3 *4 * @copyright 2024 Igor Savin <kibertoad@gmail.com>5 * @license MIT6 * @version 3.7.07 */8'use strict';9 10class FifoMap {11  constructor(max = 1000, ttlInMsecs = 0) {12    if (isNaN(max) || max < 0) {13      throw new Error('Invalid max value')14    }15 16    if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {17      throw new Error('Invalid ttl value')18    }19 20    this.first = null;21    this.items = new Map();22    this.last = null;23    this.max = max;24    this.ttl = ttlInMsecs;25  }26 27  get size() {28    return this.items.size29  }30 31  clear() {32    this.items = new Map();33    this.first = null;34    this.last = null;35  }36 37  delete(key) {38    if (this.items.has(key)) {39      const deletedItem = this.items.get(key);40 41      this.items.delete(key);42 43      if (deletedItem.prev !== null) {44        deletedItem.prev.next = deletedItem.next;45      }46 47      if (deletedItem.next !== null) {48        deletedItem.next.prev = deletedItem.prev;49      }50 51      if (this.first === deletedItem) {52        this.first = deletedItem.next;53      }54 55      if (this.last === deletedItem) {56        this.last = deletedItem.prev;57      }58    }59  }60 61  deleteMany(keys) {62    for (var i = 0; i < keys.length; i++) {63      this.delete(keys[i]);64    }65  }66 67  evict() {68    if (this.size > 0) {69      const item = this.first;70 71      this.items.delete(item.key);72 73      if (this.size === 0) {74        this.first = null;75        this.last = null;76      } else {77        this.first = item.next;78        this.first.prev = null;79      }80    }81  }82 83  expiresAt(key) {84    if (this.items.has(key)) {85      return this.items.get(key).expiry86    }87  }88 89  get(key) {90    if (this.items.has(key)) {91      const item = this.items.get(key);92 93      if (this.ttl > 0 && item.expiry <= Date.now()) {94        this.delete(key);95        return96      }97 98      return item.value99    }100  }101 102  getMany(keys) {103    const result = [];104 105    for (var i = 0; i < keys.length; i++) {106      result.push(this.get(keys[i]));107    }108 109    return result110  }111 112  keys() {113    return this.items.keys()114  }115 116  set(key, value) {117    // Replace existing item118    if (this.items.has(key)) {119      const item = this.items.get(key);120      item.value = value;121 122      item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;123 124      return125    }126 127    // Add new item128    if (this.max > 0 && this.size === this.max) {129      this.evict();130    }131 132    const item = {133      expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,134      key: key,135      prev: this.last,136      next: null,137      value,138    };139    this.items.set(key, item);140 141    if (this.size === 1) {142      this.first = item;143    } else {144      this.last.next = item;145    }146 147    this.last = item;148  }149}150 151class LruMap {152  constructor(max = 1000, ttlInMsecs = 0) {153    if (isNaN(max) || max < 0) {154      throw new Error('Invalid max value')155    }156 157    if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {158      throw new Error('Invalid ttl value')159    }160 161    this.first = null;162    this.items = new Map();163    this.last = null;164    this.max = max;165    this.ttl = ttlInMsecs;166  }167 168  get size() {169    return this.items.size170  }171 172  bumpLru(item) {173    if (this.last === item) {174      return // Item is already the last one, no need to bump175    }176 177    const last = this.last;178    const next = item.next;179    const prev = item.prev;180 181    if (this.first === item) {182      this.first = next;183    }184 185    item.next = null;186    item.prev = last;187    last.next = item;188 189    if (prev !== null) {190      prev.next = next;191    }192 193    if (next !== null) {194      next.prev = prev;195    }196 197    this.last = item;198  }199 200  clear() {201    this.items = new Map();202    this.first = null;203    this.last = null;204  }205 206  delete(key) {207    if (this.items.has(key)) {208      const item = this.items.get(key);209 210      this.items.delete(key);211 212      if (item.prev !== null) {213        item.prev.next = item.next;214      }215 216      if (item.next !== null) {217        item.next.prev = item.prev;218      }219 220      if (this.first === item) {221        this.first = item.next;222      }223 224      if (this.last === item) {225        this.last = item.prev;226      }227    }228  }229 230  deleteMany(keys) {231    for (var i = 0; i < keys.length; i++) {232      this.delete(keys[i]);233    }234  }235 236  evict() {237    if (this.size > 0) {238      const item = this.first;239 240      this.items.delete(item.key);241 242      if (this.size === 0) {243        this.first = null;244        this.last = null;245      } else {246        this.first = item.next;247        this.first.prev = null;248      }249    }250  }251 252  expiresAt(key) {253    if (this.items.has(key)) {254      return this.items.get(key).expiry255    }256  }257 258  get(key) {259    if (this.items.has(key)) {260      const item = this.items.get(key);261 262      // Item has already expired263      if (this.ttl > 0 && item.expiry <= Date.now()) {264        this.delete(key);265        return266      }267 268      // Item is still fresh269      this.bumpLru(item);270      return item.value271    }272  }273 274  getMany(keys) {275    const result = [];276 277    for (var i = 0; i < keys.length; i++) {278      result.push(this.get(keys[i]));279    }280 281    return result282  }283 284  keys() {285    return this.items.keys()286  }287 288  set(key, value) {289    // Replace existing item290    if (this.items.has(key)) {291      const item = this.items.get(key);292      item.value = value;293 294      item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;295 296      if (this.last !== item) {297        this.bumpLru(item);298      }299 300      return301    }302 303    // Add new item304    if (this.max > 0 && this.size === this.max) {305      this.evict();306    }307 308    const item = {309      expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,310      key: key,311      prev: this.last,312      next: null,313      value,314    };315    this.items.set(key, item);316 317    if (this.size === 1) {318      this.first = item;319    } else {320      this.last.next = item;321    }322 323    this.last = item;324  }325}326 327class LruObject {328  constructor(max = 1000, ttlInMsecs = 0) {329    if (isNaN(max) || max < 0) {330      throw new Error('Invalid max value')331    }332 333    if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {334      throw new Error('Invalid ttl value')335    }336 337    this.first = null;338    this.items = Object.create(null);339    this.last = null;340    this.size = 0;341    this.max = max;342    this.ttl = ttlInMsecs;343  }344 345  bumpLru(item) {346    if (this.last === item) {347      return // Item is already the last one, no need to bump348    }349 350    const last = this.last;351    const next = item.next;352    const prev = item.prev;353 354    if (this.first === item) {355      this.first = next;356    }357 358    item.next = null;359    item.prev = last;360    last.next = item;361 362    if (prev !== null) {363      prev.next = next;364    }365 366    if (next !== null) {367      next.prev = prev;368    }369 370    this.last = item;371  }372 373  clear() {374    this.items = Object.create(null);375    this.first = null;376    this.last = null;377    this.size = 0;378  }379 380  delete(key) {381    if (Object.prototype.hasOwnProperty.call(this.items, key)) {382      const item = this.items[key];383 384      delete this.items[key];385      this.size--;386 387      if (item.prev !== null) {388        item.prev.next = item.next;389      }390 391      if (item.next !== null) {392        item.next.prev = item.prev;393      }394 395      if (this.first === item) {396        this.first = item.next;397      }398 399      if (this.last === item) {400        this.last = item.prev;401      }402    }403  }404 405  deleteMany(keys) {406    for (var i = 0; i < keys.length; i++) {407      this.delete(keys[i]);408    }409  }410 411  evict() {412    if (this.size > 0) {413      const item = this.first;414 415      delete this.items[item.key];416 417      if (--this.size === 0) {418        this.first = null;419        this.last = null;420      } else {421        this.first = item.next;422        this.first.prev = null;423      }424    }425  }426 427  expiresAt(key) {428    if (Object.prototype.hasOwnProperty.call(this.items, key)) {429      return this.items[key].expiry430    }431  }432 433  get(key) {434    if (Object.prototype.hasOwnProperty.call(this.items, key)) {435      const item = this.items[key];436 437      // Item has already expired438      if (this.ttl > 0 && item.expiry <= Date.now()) {439        this.delete(key);440        return441      }442 443      // Item is still fresh444      this.bumpLru(item);445      return item.value446    }447  }448 449  getMany(keys) {450    const result = [];451 452    for (var i = 0; i < keys.length; i++) {453      result.push(this.get(keys[i]));454    }455 456    return result457  }458 459  keys() {460    return Object.keys(this.items)461  }462 463  set(key, value) {464    // Replace existing item465    if (Object.prototype.hasOwnProperty.call(this.items, key)) {466      const item = this.items[key];467      item.value = value;468 469      item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;470 471      if (this.last !== item) {472        this.bumpLru(item);473      }474 475      return476    }477 478    // Add new item479    if (this.max > 0 && this.size === this.max) {480      this.evict();481    }482 483    const item = {484      expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,485      key: key,486      prev: this.last,487      next: null,488      value,489    };490    this.items[key] = item;491 492    if (++this.size === 1) {493      this.first = item;494    } else {495      this.last.next = item;496    }497 498    this.last = item;499  }500}501 502class HitStatisticsRecord {503  constructor() {504    this.records = {};505  }506 507  initForCache(cacheId, currentTimeStamp) {508    this.records[cacheId] = {509      [currentTimeStamp]: {510        cacheSize: 0,511        hits: 0,512        falsyHits: 0,513        emptyHits: 0,514        misses: 0,515        expirations: 0,516        evictions: 0,517        invalidateOne: 0,518        invalidateAll: 0,519        sets: 0,520      },521    };522  }523 524  resetForCache(cacheId) {525    for (let key of Object.keys(this.records[cacheId])) {526      this.records[cacheId][key] = {527        cacheSize: 0,528        hits: 0,529        falsyHits: 0,530        emptyHits: 0,531        misses: 0,532        expirations: 0,533        evictions: 0,534        invalidateOne: 0,535        invalidateAll: 0,536        sets: 0,537      };538    }539  }540 541  getStatistics() {542    return this.records543  }544}545 546/**547 *548 * @param {Date} date549 * @returns {string}550 */551function getTimestamp(date) {552  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date553    .getDate()554    .toString()555    .padStart(2, '0')}`556}557 558class HitStatistics {559  constructor(cacheId, statisticTtlInHours, globalStatisticsRecord) {560    this.cacheId = cacheId;561    this.statisticTtlInHours = statisticTtlInHours;562 563    this.collectionStart = new Date();564    this.currentTimeStamp = getTimestamp(this.collectionStart);565 566    this.records = globalStatisticsRecord || new HitStatisticsRecord();567    this.records.initForCache(this.cacheId, this.currentTimeStamp);568  }569 570  get currentRecord() {571    // safety net572    /* c8 ignore next 14 */573    if (!this.records.records[this.cacheId][this.currentTimeStamp]) {574      this.records.records[this.cacheId][this.currentTimeStamp] = {575        cacheSize: 0,576        hits: 0,577        falsyHits: 0,578        emptyHits: 0,579        misses: 0,580        expirations: 0,581        evictions: 0,582        sets: 0,583        invalidateOne: 0,584        invalidateAll: 0,585      };586    }587 588    return this.records.records[this.cacheId][this.currentTimeStamp]589  }590 591  hoursPassed() {592    return (Date.now() - this.collectionStart) / 1000 / 60 / 60593  }594 595  addHit() {596    this.archiveIfNeeded();597    this.currentRecord.hits++;598  }599  addFalsyHit() {600    this.archiveIfNeeded();601    this.currentRecord.falsyHits++;602  }603 604  addEmptyHit() {605    this.archiveIfNeeded();606    this.currentRecord.emptyHits++;607  }608 609  addMiss() {610    this.archiveIfNeeded();611    this.currentRecord.misses++;612  }613 614  addEviction() {615    this.archiveIfNeeded();616    this.currentRecord.evictions++;617  }618 619  setCacheSize(currentSize) {620    this.archiveIfNeeded();621    this.currentRecord.cacheSize = currentSize;622  }623 624  addExpiration() {625    this.archiveIfNeeded();626    this.currentRecord.expirations++;627  }628 629  addSet() {630    this.archiveIfNeeded();631    this.currentRecord.sets++;632  }633 634  addInvalidateOne() {635    this.archiveIfNeeded();636    this.currentRecord.invalidateOne++;637  }638 639  addInvalidateAll() {640    this.archiveIfNeeded();641    this.currentRecord.invalidateAll++;642  }643 644  getStatistics() {645    return this.records.getStatistics()646  }647 648  archiveIfNeeded() {649    if (this.hoursPassed() >= this.statisticTtlInHours) {650      this.collectionStart = new Date();651      this.currentTimeStamp = getTimestamp(this.collectionStart);652      this.records.initForCache(this.cacheId, this.currentTimeStamp);653    }654  }655}656 657class LruObjectHitStatistics extends LruObject {658  constructor(max, ttlInMsecs, cacheId, globalStatisticsRecord, statisticTtlInHours) {659    super(max || 1000, ttlInMsecs || 0);660 661    if (!cacheId) {662      throw new Error('Cache id is mandatory')663    }664 665    this.hitStatistics = new HitStatistics(666      cacheId,667      statisticTtlInHours !== undefined ? statisticTtlInHours : 24,668      globalStatisticsRecord,669    );670  }671 672  getStatistics() {673    return this.hitStatistics.getStatistics()674  }675 676  set(key, value) {677    super.set(key, value);678    this.hitStatistics.addSet();679    this.hitStatistics.setCacheSize(this.size);680  }681 682  evict() {683    super.evict();684    this.hitStatistics.addEviction();685    this.hitStatistics.setCacheSize(this.size);686  }687 688  delete(key, isExpiration = false) {689    super.delete(key);690 691    if (!isExpiration) {692      this.hitStatistics.addInvalidateOne();693    }694    this.hitStatistics.setCacheSize(this.size);695  }696 697  clear() {698    super.clear();699 700    this.hitStatistics.addInvalidateAll();701    this.hitStatistics.setCacheSize(this.size);702  }703 704  get(key) {705    if (Object.prototype.hasOwnProperty.call(this.items, key)) {706      const item = this.items[key];707 708      // Item has already expired709      if (this.ttl > 0 && item.expiry <= Date.now()) {710        this.delete(key, true);711        this.hitStatistics.addExpiration();712        return713      }714 715      // Item is still fresh716      this.bumpLru(item);717      if (!item.value) {718        this.hitStatistics.addFalsyHit();719      }720      if (item.value === undefined || item.value === null || item.value === '') {721        this.hitStatistics.addEmptyHit();722      }723      this.hitStatistics.addHit();724      return item.value725    }726    this.hitStatistics.addMiss();727  }728}729 730class FifoObject {731  constructor(max = 1000, ttlInMsecs = 0) {732    if (isNaN(max) || max < 0) {733      throw new Error('Invalid max value')734    }735 736    if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {737      throw new Error('Invalid ttl value')738    }739 740    this.first = null;741    this.items = Object.create(null);742    this.last = null;743    this.size = 0;744    this.max = max;745    this.ttl = ttlInMsecs;746  }747 748  clear() {749    this.items = Object.create(null);750    this.first = null;751    this.last = null;752    this.size = 0;753  }754 755  delete(key) {756    if (Object.prototype.hasOwnProperty.call(this.items, key)) {757      const deletedItem = this.items[key];758 759      delete this.items[key];760      this.size--;761 762      if (deletedItem.prev !== null) {763        deletedItem.prev.next = deletedItem.next;764      }765 766      if (deletedItem.next !== null) {767        deletedItem.next.prev = deletedItem.prev;768      }769 770      if (this.first === deletedItem) {771        this.first = deletedItem.next;772      }773 774      if (this.last === deletedItem) {775        this.last = deletedItem.prev;776      }777    }778  }779 780  deleteMany(keys) {781    for (var i = 0; i < keys.length; i++) {782      this.delete(keys[i]);783    }784  }785 786  evict() {787    if (this.size > 0) {788      const item = this.first;789 790      delete this.items[item.key];791 792      if (--this.size === 0) {793        this.first = null;794        this.last = null;795      } else {796        this.first = item.next;797        this.first.prev = null;798      }799    }800  }801 802  expiresAt(key) {803    if (Object.prototype.hasOwnProperty.call(this.items, key)) {804      return this.items[key].expiry805    }806  }807 808  get(key) {809    if (Object.prototype.hasOwnProperty.call(this.items, key)) {810      const item = this.items[key];811 812      if (this.ttl > 0 && item.expiry <= Date.now()) {813        this.delete(key);814        return815      }816 817      return item.value818    }819  }820 821  getMany(keys) {822    const result = [];823 824    for (var i = 0; i < keys.length; i++) {825      result.push(this.get(keys[i]));826    }827 828    return result829  }830 831  keys() {832    return Object.keys(this.items)833  }834 835  set(key, value) {836    // Replace existing item837    if (Object.prototype.hasOwnProperty.call(this.items, key)) {838      const item = this.items[key];839      item.value = value;840 841      item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;842 843      return844    }845 846    // Add new item847    if (this.max > 0 && this.size === this.max) {848      this.evict();849    }850 851    const item = {852      expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,853      key: key,854      prev: this.last,855      next: null,856      value,857    };858    this.items[key] = item;859 860    if (++this.size === 1) {861      this.first = item;862    } else {863      this.last.next = item;864    }865 866    this.last = item;867  }868}869 870exports.Fifo = FifoObject;871exports.FifoMap = FifoMap;872exports.FifoObject = FifoObject;873exports.HitStatisticsRecord = HitStatisticsRecord;874exports.Lru = LruObject;875exports.LruHitStatistics = LruObjectHitStatistics;876exports.LruMap = LruMap;877exports.LruObject = LruObject;878exports.LruObjectHitStatistics = LruObjectHitStatistics;879