@credo-ts/core
Version:
<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1
112 lines (108 loc) • 4.34 kB
JavaScript
import { CredoError } from "../../../error/CredoError.mjs";
import { RecordDuplicateError } from "../../../error/RecordDuplicateError.mjs";
import "../../../error/index.mjs";
import { SingleContextLruCacheRecord } from "./SingleContextLruCacheRecord.mjs";
import { SingleContextLruCacheRepository } from "./SingleContextLruCacheRepository.mjs";
import LRUMap from "lru_map";
//#region src/modules/cache/singleContextLruCache/SingleContextStorageLruCache.ts
const CONTEXT_STORAGE_LRU_CACHE_ID = "CONTEXT_STORAGE_LRU_CACHE_ID";
/**
* Cache that leverages the storage associated with the agent context to store cache records.
* It will keep an in-memory cache of the records to avoid hitting the storage on every read request.
* Therefor this cache is meant to be used with a single instance of the agent.
*
* Due to keeping an in-memory copy of the cache, it is also not meant to be used with multiple
* agent context instances (meaning multi-tenancy), as they will overwrite the in-memory cache.
*
* However, this means the cache is not meant for usage with multiple instances.
*/
var SingleContextStorageLruCache = class {
constructor({ limit }) {
this.limit = limit;
}
async get(agentContext, key) {
this.assertContextCorrelationId(agentContext);
const cache = await this.getCache(agentContext);
this.removeExpiredItems(cache);
const item = cache.get(key);
if (!item) return null;
if (item.expiresAt && Date.now() > item.expiresAt) {
cache.delete(key);
await this.persistCache(agentContext);
return null;
}
return item.value;
}
async set(agentContext, key, value, expiresInSeconds) {
this.assertContextCorrelationId(agentContext);
let expiresDate;
if (expiresInSeconds) {
expiresDate = /* @__PURE__ */ new Date();
expiresDate.setSeconds(expiresDate.getSeconds() + expiresInSeconds);
}
const cache = await this.getCache(agentContext);
this.removeExpiredItems(cache);
cache.set(key, {
expiresAt: expiresDate?.getTime(),
value
});
await this.persistCache(agentContext);
}
async remove(agentContext, key) {
this.assertContextCorrelationId(agentContext);
const cache = await this.getCache(agentContext);
this.removeExpiredItems(cache);
cache.delete(key);
await this.persistCache(agentContext);
}
async getCache(agentContext) {
if (!this._cache) {
const cacheRecord = await this.fetchCacheRecord(agentContext);
this._cache = this.lruFromRecord(cacheRecord);
}
return this._cache;
}
lruFromRecord(cacheRecord) {
return new LRUMap.LRUMap(this.limit, cacheRecord.entries.entries());
}
async fetchCacheRecord(agentContext) {
const cacheRepository = agentContext.dependencyManager.resolve(SingleContextLruCacheRepository);
let cacheRecord = await cacheRepository.findById(agentContext, CONTEXT_STORAGE_LRU_CACHE_ID);
if (!cacheRecord) {
cacheRecord = new SingleContextLruCacheRecord({
id: CONTEXT_STORAGE_LRU_CACHE_ID,
entries: /* @__PURE__ */ new Map()
});
try {
await cacheRepository.save(agentContext, cacheRecord);
} catch (error) {
if (error instanceof RecordDuplicateError) return cacheRepository.getById(agentContext, CONTEXT_STORAGE_LRU_CACHE_ID);
throw error;
}
}
return cacheRecord;
}
removeExpiredItems(cache) {
cache.forEach((value, key) => {
if (value.expiresAt && Date.now() > value.expiresAt) cache.delete(key);
});
}
async persistCache(agentContext) {
const cacheRepository = agentContext.dependencyManager.resolve(SingleContextLruCacheRepository);
const cache = await this.getCache(agentContext);
await cacheRepository.update(agentContext, new SingleContextLruCacheRecord({
entries: new Map(cache.toJSON().map(({ key, value }) => [key, value])),
id: CONTEXT_STORAGE_LRU_CACHE_ID
}));
}
/**
* Asserts this class is not used with multiple agent context instances.
*/
assertContextCorrelationId(agentContext) {
if (!this._contextCorrelationId) this._contextCorrelationId = agentContext.contextCorrelationId;
if (this._contextCorrelationId !== agentContext.contextCorrelationId) throw new CredoError("SingleContextStorageLruCache can not be used with multiple agent context instances. Register a custom cache implementation in the CacheModule.");
}
};
//#endregion
export { SingleContextStorageLruCache };
//# sourceMappingURL=SingleContextStorageLruCache.mjs.map