@itwin/core-backend
Version:
iTwin.js backend components
120 lines • 4.52 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElementLRUCache = void 0;
/**
* A LRU cache for entities. Cache contains the ElementProps and the load options used to load it.
* Cache can be searched by id, code or federationGuid.
*/
class ElementLRUCache {
capacity;
static DEFAULT_CAPACITY = 2000;
_elementCache = new Map();
_cacheByCode = new Map();
_cacheByFederationGuid = new Map();
static makeCodeKey(code) {
const keys = [code.scope, code.spec];
if (code.value !== undefined) {
keys.push(code.value);
}
return JSON.stringify(keys);
}
findElement(key) {
if (key.id) {
return this._elementCache.get(key.id);
}
else if (key.federationGuid) {
const id = this._cacheByFederationGuid.get(key.federationGuid);
if (id)
return this._elementCache.get(id);
}
else if (key.code) {
const id = this._cacheByCode.get(ElementLRUCache.makeCodeKey(key.code));
if (id)
return this._elementCache.get(id);
}
else {
throw new Error("No key provided");
}
return undefined;
}
constructor(capacity = ElementLRUCache.DEFAULT_CAPACITY) {
this.capacity = capacity;
}
clear() {
this._elementCache.clear();
this._cacheByCode.clear();
this._cacheByFederationGuid.clear();
}
get size() {
return this._elementCache.size;
}
deleteWithModel(modelId) {
this._elementCache.forEach((cachedVal, elementId) => {
if (cachedVal.elProps.model === modelId)
this.delete({ id: elementId });
});
}
delete(key) {
const cachedElement = this.findElement(key);
if (cachedElement) {
if (cachedElement.elProps.id)
this._elementCache.delete(cachedElement.elProps.id);
this._cacheByCode.delete(ElementLRUCache.makeCodeKey(cachedElement.elProps.code));
if (cachedElement.elProps.federationGuid)
this._cacheByFederationGuid.delete(cachedElement.elProps.federationGuid);
return true;
}
return false;
}
get(key) {
const cachedElement = this.findElement(key);
if (cachedElement) {
if (cachedElement.elProps.id) {
this._elementCache.delete(cachedElement.elProps.id);
this._elementCache.set(cachedElement.elProps.id, cachedElement);
}
}
if (cachedElement) {
if (key.displayStyle !== cachedElement.loadOptions.displayStyle ||
key.onlyBaseProperties !== cachedElement.loadOptions.onlyBaseProperties ||
key.renderTimeline !== cachedElement.loadOptions.renderTimeline ||
key.wantBRepData !== cachedElement.loadOptions.wantBRepData ||
key.wantGeometry !== cachedElement.loadOptions.wantGeometry) {
return undefined;
}
}
return cachedElement;
}
set(el) {
if (!el.elProps.id)
throw new Error("Element must have an id");
// do not cache this element as geom need to be rerender into geom props if any part changes
// TODO: find a way to handle caching geometry
if (el.loadOptions.wantGeometry) {
return this;
}
if (this._elementCache.has(el.elProps.id)) {
this._elementCache.delete(el.elProps.id);
this._elementCache.set(el.elProps.id, el);
}
else {
this._elementCache.set(el.elProps.id, el);
}
if (el.elProps.federationGuid) {
this._cacheByFederationGuid.set(el.elProps.federationGuid, el.elProps.id);
}
this._cacheByCode.set(ElementLRUCache.makeCodeKey(el.elProps.code), el.elProps.id);
if (this._elementCache.size > this.capacity) {
const oldestKey = this._elementCache.keys().next().value;
const oldestElement = this._elementCache.get(oldestKey);
this.delete({ id: oldestKey, federationGuid: oldestElement?.elProps.federationGuid, code: oldestElement?.elProps.code });
}
return this;
}
get [Symbol.toStringTag]() {
return `EntityCache(this.size=${this.size}, capacity=${this.capacity})`;
}
}
exports.ElementLRUCache = ElementLRUCache;
;
//# sourceMappingURL=ElementLRUCache.js.map