UNPKG

@titansys/persistent-cache

Version:

A robust, enterprise-grade persistent cache with file locking, corruption detection, health monitoring, and graceful degradation.

422 lines (331 loc) โ€ข 10.9 kB
# persistent-cache A robust, enterprise-grade Node.js module for persistent caching with advanced features including file locking, corruption detection, health monitoring, and graceful degradation. ## ๐Ÿš€ Features - **๐Ÿ”’ Concurrent-Safe**: File locking prevents race conditions and data corruption - **๐Ÿ›ก๏ธ Corruption Detection**: JSON validation with automatic error recovery - **๐Ÿ“Š Health Monitoring**: Real-time cache health tracking and reporting - **๐Ÿ”„ Graceful Degradation**: Continues operation even with partial corruption - **โšก High Performance**: Memory + disk hybrid caching for optimal speed - **๐Ÿ”ง Zero Breaking Changes**: Fully backward compatible with v1.x - **๐Ÿ” Security Hardened**: All known vulnerabilities patched ## ๐Ÿ“ฆ Installation ```bash npm install @titansys/persistent-cache ``` ## ๐ŸŽฏ Quick Start ```js const cache = require('@titansys/persistent-cache'); // Create a cache instance const myCache = cache(); // Store data myCache.put('user:123', { name: 'John', email: 'john@example.com' }, (err) => { if (err) throw err; console.log('User saved to cache'); }); // Retrieve data myCache.get('user:123', (err, user) => { if (err) throw err; console.log('Retrieved user:', user); }); ``` ## ๐Ÿ“š Core API ### Basic Operations #### `cache.put(key, data, callback)` Asynchronously stores data in the cache. ```js cache.put('myKey', { foo: 'bar' }, (err) => { if (err) console.error('Cache error:', err); else console.log('Data cached successfully'); }); ``` #### `cache.putSync(key, data)` Synchronously stores data in the cache. ```js try { cache.putSync('myKey', { foo: 'bar' }); console.log('Data cached successfully'); } catch (err) { console.error('Cache error:', err); } ``` #### `cache.get(key, callback)` Asynchronously retrieves data from the cache. ```js cache.get('myKey', (err, data) => { if (err) console.error('Cache error:', err); else if (data === undefined) console.log('Key not found'); else console.log('Retrieved:', data); }); ``` #### `cache.getSync(key)` Synchronously retrieves data from the cache. ```js try { const data = cache.getSync('myKey'); if (data === undefined) { console.log('Key not found'); } else { console.log('Retrieved:', data); } } catch (err) { console.error('Cache error:', err); } ``` #### `cache.delete(key, callback)` / `cache.deleteSync(key)` Removes an entry from the cache. ```js // Async cache.delete('myKey', (err) => { if (err) console.error('Delete error:', err); else console.log('Key deleted'); }); // Sync try { cache.deleteSync('myKey'); console.log('Key deleted'); } catch (err) { console.error('Delete error:', err); } ``` #### `cache.keys(callback)` / `cache.keysSync()` Lists all keys in the cache. ```js // Async cache.keys((err, keys) => { if (err) console.error('Keys error:', err); else console.log('Cache keys:', keys); }); // Sync try { const keys = cache.keysSync(); console.log('Cache keys:', keys); } catch (err) { console.error('Keys error:', err); } ``` #### `cache.unlink(callback)` Completely removes the cache directory and all its contents. ```js cache.unlink((err) => { if (err) console.error('Unlink error:', err); else console.log('Cache completely removed'); }); ``` ## ๐Ÿฅ Health Monitoring API ### `cache.healthCheck(callback)` Performs a comprehensive health check of all cache files. ```js cache.healthCheck((err, report) => { if (err) { console.error('Health check failed:', err); return; } console.log('Health Report:'); console.log(`โœ… Healthy files: ${report.healthy}`); console.log(`โŒ Corrupted files: ${report.corrupted}`); console.log(`๐Ÿ”ง Repaired files: ${report.repaired}`); // Detailed file status report.files.forEach(file => { console.log(`${file.name}: ${file.status}`); if (file.error) console.log(` Error: ${file.error}`); }); }); ``` ### `cache.healthCheckSync()` Synchronous version of health check. ```js try { const report = cache.healthCheckSync(); console.log('Health report:', report); } catch (err) { console.error('Health check failed:', err); } ``` ### `cache.startHealthMonitoring(callback)` Starts periodic health monitoring. ```js cache.startHealthMonitoring((err, report) => { if (err) { console.error('Health monitoring error:', err); return; } if (report.corrupted > 0) { console.warn(`โš ๏ธ Found ${report.corrupted} corrupted files`); // Take action: alert, repair, etc. } }); console.log('Health monitoring started'); ``` ### `cache.stopHealthMonitoring()` Stops periodic health monitoring. ```js cache.stopHealthMonitoring(); console.log('Health monitoring stopped'); ``` ### `cache.isHealthMonitoring()` Check if health monitoring is currently active. ```js if (cache.isHealthMonitoring()) { console.log('Health monitoring is active'); } else { console.log('Health monitoring is inactive'); } ``` ## โš™๏ธ Configuration Options ```js const cache = require('@titansys/persistent-cache'); const myCache = cache({ base: './my-cache', // Base directory name: 'user-cache', // Cache name duration: 24 * 60 * 60 * 1000, // 24 hours in ms memory: true, // Enable memory caching persist: true, // Enable disk persistence // ๐Ÿ†• Robustness Options lockTimeout: 10000, // Lock timeout in ms (default: 5000) healthCheckInterval: 300000, // Health check interval in ms (default: 5 min) autoRepair: true // Auto-remove corrupted files (default: false) }); ``` ### Core Options #### `options.base` - **Type**: `string` - **Default**: Main module directory - **Description**: Base directory where cache files are stored #### `options.name` - **Type**: `string` - **Default**: `'cache'` - **Description**: Cache name (creates subdirectory `base/name`) #### `options.duration` - **Type**: `number` - **Default**: `undefined` (infinite) - **Description**: Cache entry TTL in milliseconds #### `options.memory` - **Type**: `boolean` - **Default**: `true` - **Description**: Enable in-memory caching for performance #### `options.persist` - **Type**: `boolean` - **Default**: `true` - **Description**: Enable disk persistence ### ๐Ÿ†• Robustness Options #### `options.lockTimeout` - **Type**: `number` - **Default**: `5000` - **Description**: File lock timeout in milliseconds. Prevents indefinite blocking on concurrent access. #### `options.healthCheckInterval` - **Type**: `number` - **Default**: `300000` (5 minutes) - **Description**: Interval for periodic health checks when monitoring is enabled. #### `options.autoRepair` - **Type**: `boolean` - **Default**: `false` - **Description**: Automatically remove corrupted cache files during health checks. ## ๐Ÿ”’ Concurrency & Locking The cache uses file-based locking to prevent race conditions: ```js // Multiple processes can safely write to the same cache const cache1 = require('persistent-cache')({ name: 'shared' }); const cache2 = require('persistent-cache')({ name: 'shared' }); // These operations are safe to run concurrently cache1.put('key1', 'value1', callback1); cache2.put('key2', 'value2', callback2); ``` **Lock Features:** - โฑ๏ธ Configurable timeout (default: 5 seconds) - ๐Ÿงน Automatic cleanup on process exit - ๐Ÿ”„ Stale lock detection and recovery - ๐Ÿšซ Deadlock prevention ## ๐Ÿ›ก๏ธ Error Handling & Graceful Degradation The cache handles errors gracefully without breaking your application: ```js const cache = require('persistent-cache')(); // Even if cache files are corrupted, operations continue cache.get('potentially-corrupted-key', (err, data) => { // err will be null, data will be undefined for corrupted entries // Warning logged to console for debugging if (data === undefined) { console.log('Key not found or corrupted - using fallback'); // Your fallback logic here } }); ``` **Graceful Degradation Features:** - ๐Ÿ“ Corrupted files return `undefined` instead of throwing errors - โš ๏ธ Warning logs for debugging (can be disabled) - ๐Ÿ”„ Memory fallback when disk operations fail - ๐ŸŽฏ Isolated corruption (bad entries don't affect good ones) ## ๐Ÿ” Security - โœ… **Zero Vulnerabilities**: All dependencies updated to secure versions - ๐Ÿ”’ **File Locking**: Prevents concurrent write corruption - ๐Ÿ›ก๏ธ **Input Validation**: JSON structure validation before parsing - ๐Ÿงน **Safe Cleanup**: Proper lock cleanup on process termination ## ๐Ÿ“Š Performance - **Memory + Disk Hybrid**: Best of both worlds - **Efficient Locking**: Minimal performance overhead - **Lazy Validation**: Only validates on read operations - **Background Monitoring**: Health checks don't block operations ### Benchmarks ``` Memory Cache: ~0.1ms per operation Disk Cache: ~1-5ms per operation (depending on file size) Lock Acquisition: ~0.5ms average Health Check: ~10ms per 100 files ``` ## ๐Ÿ”„ Migration from v1.x No code changes required! All v1.x APIs work exactly the same: ```js // v1.x code works unchanged const cache = require('persistent-cache')(); cache.put('key', 'value', callback); cache.get('key', callback); ``` **New features are opt-in:** - Health monitoring is disabled by default - Auto-repair is disabled by default - All new APIs are additive ## ๐Ÿ› Troubleshooting ### Health Check Issues ```js cache.healthCheck((err, report) => { if (report.corrupted > 0) { console.log('Corrupted files found:', report.files.filter(f => f.status === 'corrupted')); // Option 1: Enable auto-repair const repairedCache = require('persistent-cache')({ name: 'same-cache', autoRepair: true }); // Option 2: Manual cleanup report.files .filter(f => f.status === 'corrupted') .forEach(f => cache.delete(f.name, () => {})); } }); ``` ### Lock Timeout Issues ```js // Increase timeout for slow systems const cache = require('persistent-cache')({ lockTimeout: 15000 // 15 seconds }); ``` ### Performance Tuning ```js // Memory-only for maximum speed const fastCache = require('persistent-cache')({ persist: false, memory: true }); // Disk-only for memory constrained environments const diskCache = require('persistent-cache')({ persist: true, memory: false }); ``` ## ๐Ÿ“œ License MIT ## ๐Ÿ‘ฅ Author **Titan Systems** - [https://github.com/titansys](https://github.com/titansys) ## ๐Ÿ”— Links - [GitHub Repository](https://github.com/titansys/persistent-cache) - [Issue Tracker](https://github.com/titansys/persistent-cache/issues) - [npm Package](https://www.npmjs.com/package/@titansys/persistent-cache)