Files
sell/middlelayer/utils/cache.ts

83 lines
2.4 KiB
TypeScript

import { cacheConfig } from "../config/cache.js";
import { cacheHits, cacheMisses } from "../monitoring/metrics.js";
import { logCacheHit, logCacheMiss } from "../monitoring/logger.js";
import { RedisCache } from "./redisCache.js";
/**
* Cache-Interface für Abstraktion
*/
export interface CacheInterface<T> {
set(key: string, data: T, ttl?: number): void | Promise<void>;
get(key: string): T | null | Promise<T | null>;
clear(): void | Promise<void>;
delete(key: string): void | Promise<void>;
}
/**
* In-Memory Cache (Fallback wenn Redis nicht verfügbar)
*/
class InMemoryCache<T> implements CacheInterface<T> {
private cache = new Map<string, { data: T; expiresAt: number }>();
private defaultTTL: number;
private cacheType: string;
constructor(defaultTTL: number, cacheType: string) {
this.defaultTTL = defaultTTL;
this.cacheType = cacheType;
}
async set(key: string, data: T, ttl?: number): Promise<void> {
const expiresAt = Date.now() + (ttl || this.defaultTTL);
this.cache.set(key, { data, expiresAt });
}
async get(key: string): Promise<T | null> {
const entry = this.cache.get(key);
if (!entry) {
cacheMisses.inc({ cache_type: this.cacheType });
logCacheMiss(key, this.cacheType);
return null;
}
if (Date.now() > entry.expiresAt) {
this.cache.delete(key);
cacheMisses.inc({ cache_type: this.cacheType });
logCacheMiss(key, this.cacheType);
return null;
}
cacheHits.inc({ cache_type: this.cacheType });
logCacheHit(key, this.cacheType);
return entry.data;
}
async clear(): Promise<void> {
this.cache.clear();
}
async delete(key: string): Promise<void> {
this.cache.delete(key);
}
}
/**
* Cache-Instanzen
* Verwendet Redis wenn aktiviert, sonst In-Memory
*/
const useRedis = process.env["REDIS_ENABLED"] === "true";
export const cache = {
pages: useRedis
? new RedisCache<any>(cacheConfig.pages.ttl, "pages")
: new InMemoryCache<any>(cacheConfig.pages.ttl, "pages"),
pageSeo: useRedis
? new RedisCache<any>(cacheConfig.pageSeo.ttl, "pageSeo")
: new InMemoryCache<any>(cacheConfig.pageSeo.ttl, "pageSeo"),
navigation: useRedis
? new RedisCache<any>(cacheConfig.navigation.ttl, "navigation")
: new InMemoryCache<any>(cacheConfig.navigation.ttl, "navigation"),
products: useRedis
? new RedisCache<any>(cacheConfig.products.ttl, "products")
: new InMemoryCache<any>(cacheConfig.products.ttl, "products"),
};