updateweb
This commit is contained in:
143
backend/middleware/cache.js
Normal file
143
backend/middleware/cache.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* In-Memory Cache Middleware
|
||||
* Caches API responses to reduce database load
|
||||
*/
|
||||
const logger = require("../config/logger");
|
||||
|
||||
class CacheManager {
|
||||
constructor(defaultTTL = 300000) {
|
||||
// 5 minutes default
|
||||
this.cache = new Map();
|
||||
this.defaultTTL = defaultTTL;
|
||||
}
|
||||
|
||||
set(key, value, ttl = this.defaultTTL) {
|
||||
const expiresAt = Date.now() + ttl;
|
||||
this.cache.set(key, { value, expiresAt });
|
||||
logger.debug(`Cache set: ${key} (TTL: ${ttl}ms)`);
|
||||
}
|
||||
|
||||
get(key) {
|
||||
const cached = this.cache.get(key);
|
||||
if (!cached) return null;
|
||||
|
||||
if (Date.now() > cached.expiresAt) {
|
||||
this.cache.delete(key);
|
||||
logger.debug(`Cache expired: ${key}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug(`Cache hit: ${key}`);
|
||||
return cached.value;
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
const deleted = this.cache.delete(key);
|
||||
if (deleted) logger.debug(`Cache invalidated: ${key}`);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
deletePattern(pattern) {
|
||||
let count = 0;
|
||||
for (const key of this.cache.keys()) {
|
||||
if (key.includes(pattern)) {
|
||||
this.cache.delete(key);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0)
|
||||
logger.debug(`Cache pattern invalidated: ${pattern} (${count} keys)`);
|
||||
return count;
|
||||
}
|
||||
|
||||
clear() {
|
||||
const size = this.cache.size;
|
||||
this.cache.clear();
|
||||
logger.info(`Cache cleared (${size} keys)`);
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.cache.size;
|
||||
}
|
||||
|
||||
// Clean up expired entries
|
||||
cleanup() {
|
||||
const now = Date.now();
|
||||
let cleaned = 0;
|
||||
for (const [key, { expiresAt }] of this.cache.entries()) {
|
||||
if (now > expiresAt) {
|
||||
this.cache.delete(key);
|
||||
cleaned++;
|
||||
}
|
||||
}
|
||||
if (cleaned > 0)
|
||||
logger.debug(`Cache cleanup: removed ${cleaned} expired entries`);
|
||||
return cleaned;
|
||||
}
|
||||
}
|
||||
|
||||
// Global cache instance
|
||||
const cache = new CacheManager();
|
||||
|
||||
// Cleanup interval reference (for graceful shutdown)
|
||||
let cleanupInterval = null;
|
||||
|
||||
// Start automatic cleanup (optional, call from server startup)
|
||||
const startCleanup = () => {
|
||||
if (!cleanupInterval) {
|
||||
cleanupInterval = setInterval(() => cache.cleanup(), 300000); // 5 minutes
|
||||
logger.debug("Cache cleanup scheduler started");
|
||||
}
|
||||
};
|
||||
|
||||
// Stop automatic cleanup (for graceful shutdown)
|
||||
const stopCleanup = () => {
|
||||
if (cleanupInterval) {
|
||||
clearInterval(cleanupInterval);
|
||||
cleanupInterval = null;
|
||||
logger.debug("Cache cleanup scheduler stopped");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache middleware factory
|
||||
* @param {number} ttl - Time to live in milliseconds
|
||||
* @param {function} keyGenerator - Function to generate cache key from req
|
||||
*/
|
||||
const cacheMiddleware = (ttl = 300000, keyGenerator = null) => {
|
||||
return (req, res, next) => {
|
||||
// Skip cache for authenticated requests
|
||||
if (req.session && req.session.userId) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const key = keyGenerator
|
||||
? keyGenerator(req)
|
||||
: `${req.method}:${req.originalUrl}`;
|
||||
|
||||
const cachedResponse = cache.get(key);
|
||||
if (cachedResponse) {
|
||||
res.setHeader("X-Cache", "HIT");
|
||||
return res.json(cachedResponse);
|
||||
}
|
||||
|
||||
// Store original json method
|
||||
const originalJson = res.json.bind(res);
|
||||
|
||||
// Override json method to cache response
|
||||
res.json = function (data) {
|
||||
cache.set(key, data, ttl);
|
||||
res.setHeader("X-Cache", "MISS");
|
||||
return originalJson(data);
|
||||
};
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
cache,
|
||||
cacheMiddleware,
|
||||
startCleanup,
|
||||
stopCleanup,
|
||||
};
|
||||
Reference in New Issue
Block a user