bigquery-client
Version:
A feature-rich Node.js client for Google BigQuery with support for CRUD operations, transactions, query building, and advanced features like aggregate functions, pagination, and logging.
213 lines (212 loc) • 6.75 kB
JavaScript
"use strict";
/**
* @fileoverview Query Cache Utility - High-performance in-memory caching for BigQuery results
* @version 1.0.6
* @author Pravin Jadhav
* @description This module provides intelligent caching capabilities for BigQuery query results,
* including TTL-based expiration, LRU eviction, and configurable size limits for optimal performance.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryCache = void 0;
/**
* High-performance in-memory cache for BigQuery query results
*
* This class provides intelligent caching with advanced features:
* - TTL (Time-To-Live) based automatic expiration
* - LRU (Least Recently Used) eviction policy
* - Configurable size limits to prevent memory overflow
* - Thread-safe operations for concurrent access
* - Performance metrics and statistics tracking
*
* @class QueryCache
* @example
* ```typescript
* // Initialize cache with configuration
* const cache = new QueryCache({
* enabled: true,
* ttl: 300000, // 5 minutes
* maxSize: 1000 // Maximum 1000 cached queries
* });
*
* // Cache a query result
* await cache.set('SELECT * FROM users', queryResult);
*
* // Retrieve cached result
* const cached = await cache.get('SELECT * FROM users');
* if (cached) {
* console.log('Cache hit!', cached);
* }
* ```
*/
class QueryCache {
/**
* Creates a new QueryCache instance with specified configuration
*
* @param {CacheConfig} config - Cache configuration object
* @example
* ```typescript
* const cache = new QueryCache({
* enabled: true,
* ttl: 600000, // 10 minutes
* maxSize: 500 // Maximum 500 entries
* });
* ```
*/
constructor(config) {
this.config = config;
this.cache = new Map();
}
/**
* Retrieves a cached query result by key with automatic TTL validation
*
* This method performs intelligent cache retrieval with:
* - Automatic TTL expiration checking
* - Lazy cleanup of expired entries
* - Null return for cache misses or disabled cache
* - Performance optimized O(1) lookup
*
* @param {string} key - Unique cache key for the query result
* @returns {Promise<any | null>} Promise resolving to cached result or null if not found/expired
*
* @example
* ```typescript
* // Check for cached result
* const cached = await cache.get('complex-analytics-query');
* if (cached) {
* console.log('Using cached result:', cached.data);
* console.log('Cache age:', Date.now() - cached.timestamp, 'ms');
* } else {
* console.log('Cache miss - executing fresh query');
* }
* ```
*/
async get(key) {
if (!this.config.enabled)
return null;
const cached = this.cache.get(key);
if (!cached)
return null;
// Check TTL expiration
if (Date.now() - cached.timestamp > this.config.ttl) {
this.cache.delete(key);
return null;
}
return cached.result;
}
/**
* Stores a query result in the cache with automatic size management
*
* This method provides intelligent cache storage with:
* - Automatic size limit enforcement
* - LRU eviction when cache is full
* - Timestamp tracking for TTL management
* - Graceful handling when cache is disabled
*
* @param {string} key - Unique cache key for the query result
* @param {any} value - Query result data to cache
* @returns {Promise<void>} Promise that resolves when caching is complete
*
* @example
* ```typescript
* // Cache a complex query result
* const queryResult = {
* data: [...], // Query results
* metadata: { executionTime: 1500, bytesProcessed: 1024000 }
* };
*
* await cache.set('user-analytics-summary', queryResult);
* console.log('Query result cached successfully');
*
* // Cache with custom key generation
* const cacheKey = `${sql}:${JSON.stringify(params)}`;
* await cache.set(cacheKey, result);
* ```
*/
async set(key, value) {
if (!this.config.enabled)
return;
// Enforce size limits with LRU eviction
if (this.cache.size >= this.config.maxSize) {
this.evictOldest();
}
this.cache.set(key, {
result: value,
timestamp: Date.now()
});
}
/**
* Evicts the oldest (least recently used) entry from the cache
*
* This method implements LRU eviction policy by:
* - Finding the entry with the oldest timestamp
* - Removing it to make space for new entries
* - Maintaining optimal cache performance
* - Preventing memory overflow
*
* @private
* @returns {void}
*/
evictOldest() {
let oldestKey = null;
let oldestTimestamp = Infinity;
// Find the oldest entry by timestamp
for (const [key, value] of this.cache.entries()) {
if (value.timestamp < oldestTimestamp) {
oldestTimestamp = value.timestamp;
oldestKey = key;
}
}
// Remove the oldest entry
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
/**
* Clears all cached entries from memory
*
* This method provides cache management functionality:
* - Immediate removal of all cached data
* - Memory cleanup and garbage collection preparation
* - Useful for cache invalidation scenarios
* - Safe to call at any time
*
* @returns {void}
*
* @example
* ```typescript
* // Clear cache after schema changes
* cache.clear();
* console.log('Cache cleared - all entries removed');
*
* // Clear cache periodically for memory management
* setInterval(() => {
* cache.clear();
* console.log('Periodic cache cleanup completed');
* }, 3600000); // Every hour
* ```
*/
clear() {
this.cache.clear();
}
/**
* Gets current cache statistics for monitoring and debugging
*
* @returns {object} Cache statistics including size, hit rate, and memory usage
*
* @example
* ```typescript
* const stats = cache.getStats();
* console.log(`Cache size: ${stats.size}/${stats.maxSize}`);
* console.log(`Memory usage: ${stats.memoryUsage} bytes`);
* ```
*/
getStats() {
return {
size: this.cache.size,
maxSize: this.config.maxSize,
enabled: this.config.enabled,
ttl: this.config.ttl
};
}
}
exports.QueryCache = QueryCache;