UNPKG

@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
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