

const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.js');
const require_CredoError = require('../../../error/CredoError.js');
const require_RecordDuplicateError = require('../../../error/RecordDuplicateError.js');
require('../../../error/index.js');
const require_SingleContextLruCacheRecord = require('./SingleContextLruCacheRecord.js');
const require_SingleContextLruCacheRepository = require('./SingleContextLruCacheRepository.js');
let lru_map = require("lru_map");
lru_map = require_rolldown_runtime.__toESM(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 lru_map.default.LRUMap(this.limit, cacheRecord.entries.entries());
	}
	async fetchCacheRecord(agentContext) {
		const cacheRepository = agentContext.dependencyManager.resolve(require_SingleContextLruCacheRepository.SingleContextLruCacheRepository);
		let cacheRecord = await cacheRepository.findById(agentContext, CONTEXT_STORAGE_LRU_CACHE_ID);
		if (!cacheRecord) {
			cacheRecord = new require_SingleContextLruCacheRecord.SingleContextLruCacheRecord({
				id: CONTEXT_STORAGE_LRU_CACHE_ID,
				entries: /* @__PURE__ */ new Map()
			});
			try {
				await cacheRepository.save(agentContext, cacheRecord);
			} catch (error) {
				if (error instanceof require_RecordDuplicateError.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(require_SingleContextLruCacheRepository.SingleContextLruCacheRepository);
		const cache = await this.getCache(agentContext);
		await cacheRepository.update(agentContext, new require_SingleContextLruCacheRecord.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 require_CredoError.CredoError("SingleContextStorageLruCache can not be used with multiple agent context instances. Register a custom cache implementation in the CacheModule.");
	}
};

//#endregion
exports.SingleContextStorageLruCache = SingleContextStorageLruCache;