aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
234 lines (207 loc) • 4.7 kB
JavaScript
/**
* Configuration Cache
*
* Provides caching for configuration data with TTL (time-to-live) support.
* Part of Story 6.1.2.6: Framework Configuration System
*
* @module core/config/config-cache
* @migrated Story 2.2 - Core Module Creation
*/
/**
* Configuration Cache Class
*
* Caches configuration data with automatic expiration
*/
class ConfigCache {
/**
* Create a new ConfigCache
*
* @param {number} ttl - Time-to-live in milliseconds (default: 5 minutes)
*/
constructor(ttl = 5 * 60 * 1000) {
this.cache = new Map();
this.timestamps = new Map();
this.ttl = ttl;
this.hits = 0;
this.misses = 0;
}
/**
* Get value from cache
*
* @param {string} key - Cache key
* @returns {*} Cached value or null if not found/expired
*/
get(key) {
if (!this.cache.has(key)) {
this.misses++;
return null;
}
const timestamp = this.timestamps.get(key);
const now = Date.now();
// Check if expired
if (now - timestamp > this.ttl) {
this.cache.delete(key);
this.timestamps.delete(key);
this.misses++;
return null;
}
this.hits++;
return this.cache.get(key);
}
/**
* Set value in cache
*
* @param {string} key - Cache key
* @param {*} value - Value to cache
*/
set(key, value) {
this.cache.set(key, value);
this.timestamps.set(key, Date.now());
}
/**
* Check if key exists in cache (and is not expired)
*
* @param {string} key - Cache key
* @returns {boolean} True if key exists and is valid
*/
has(key) {
return this.get(key) !== null;
}
/**
* Invalidate (delete) a specific cache entry
*
* @param {string} key - Cache key to invalidate
* @returns {boolean} True if entry was deleted
*/
invalidate(key) {
const deleted = this.cache.delete(key);
this.timestamps.delete(key);
return deleted;
}
/**
* Clear all cache entries
*/
clear() {
this.cache.clear();
this.timestamps.clear();
this.hits = 0;
this.misses = 0;
}
/**
* Clear expired entries
*
* @returns {number} Number of entries cleared
*/
clearExpired() {
const now = Date.now();
let cleared = 0;
for (const [key, timestamp] of this.timestamps.entries()) {
if (now - timestamp > this.ttl) {
this.cache.delete(key);
this.timestamps.delete(key);
cleared++;
}
}
return cleared;
}
/**
* Get cache size
*
* @returns {number} Number of entries in cache
*/
get size() {
return this.cache.size;
}
/**
* Get cache statistics
*
* @returns {Object} Cache statistics
*/
getStats() {
const total = this.hits + this.misses;
const hitRate = total > 0 ? (this.hits / total * 100).toFixed(1) : '0.0';
return {
size: this.size,
hits: this.hits,
misses: this.misses,
total,
hitRate: `${hitRate}%`,
ttl: this.ttl,
ttlMinutes: (this.ttl / 1000 / 60).toFixed(1),
};
}
/**
* Reset statistics (but keep cache)
*/
resetStats() {
this.hits = 0;
this.misses = 0;
}
/**
* Get all cache keys
*
* @returns {string[]} Array of cache keys
*/
keys() {
return Array.from(this.cache.keys());
}
/**
* Get all cache entries
*
* @returns {Array<{key: string, value: *, age: number}>} Array of entries with age
*/
entries() {
const now = Date.now();
const entries = [];
for (const [key, value] of this.cache.entries()) {
const timestamp = this.timestamps.get(key);
const age = now - timestamp;
entries.push({
key,
value,
age,
ageSeconds: (age / 1000).toFixed(1),
expires: this.ttl - age,
expiresSeconds: ((this.ttl - age) / 1000).toFixed(1),
});
}
return entries;
}
/**
* Set new TTL
*
* @param {number} ttl - New TTL in milliseconds
*/
setTTL(ttl) {
this.ttl = ttl;
}
/**
* Serialize cache to JSON
*
* @returns {string} JSON string
*/
toJSON() {
return JSON.stringify({
size: this.size,
stats: this.getStats(),
entries: this.entries().map(e => ({
key: e.key,
age: e.ageSeconds,
expires: e.expiresSeconds,
})),
}, null, 2);
}
}
// Global cache instance (singleton)
const globalConfigCache = new ConfigCache();
// Auto cleanup expired entries every minute
setInterval(() => {
const cleared = globalConfigCache.clearExpired();
if (cleared > 0) {
console.log(`🗑️ Config cache: Cleared ${cleared} expired entries`);
}
}, 60 * 1000);
module.exports = {
ConfigCache,
globalConfigCache,
};