// In-memory cache for stock prices to improve performance
// Cache expires after 2 minutes to balance freshness with performance
interface CacheEntry {
price: number;
timestamp: number;
}
class PriceCache {
private cache: Map<string, CacheEntry> = new Map();
private readonly TTL_MS = 2 * 60 * 1000; // 2 minutes
get(symbol: string): number | null {
const entry = this.cache.get(symbol);
if (!entry) {
return null;
}
// Check if cache entry is still valid
const now = Date.now();
if (now - entry.timestamp > this.TTL_MS) {
this.cache.delete(symbol);
return null;
}
return entry.price;
}
set(symbol: string, price: number): void {
this.cache.set(symbol, {
price,
timestamp: Date.now(),
});
}
setMultiple(prices: Record<string, number>): void {
const timestamp = Date.now();
for (const [symbol, price] of Object.entries(prices)) {
this.cache.set(symbol, { price, timestamp });
}
}
clear(): void {
this.cache.clear();
}
// Get symbols that need to be fetched (not in cache or expired)
getSymbolsToFetch(symbols: string[]): string[] {
return symbols.filter(symbol => this.get(symbol) === null);
}
// Get cached prices for symbols that are available
getCachedPrices(symbols: string[]): Record<string, number> {
const prices: Record<string, number> = {};
for (const symbol of symbols) {
const price = this.get(symbol);
if (price !== null) {
prices[symbol] = price;
}
}
return prices;
}
// Get cache stats for debugging
getStats(): { size: number; symbols: string[] } {
return {
size: this.cache.size,
symbols: Array.from(this.cache.keys()),
};
}
}
// Singleton instance
const priceCache = new PriceCache();
export default priceCache;