Package Exports
- @titansys/persistent-cache
- @titansys/persistent-cache/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@titansys/persistent-cache) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
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
npm install @titansys/persistent-cache๐ฏ Quick Start
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.
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.
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.
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.
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.
// 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.
// 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.
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.
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.
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.
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.
cache.stopHealthMonitoring();
console.log('Health monitoring stopped');cache.isHealthMonitoring()
Check if health monitoring is currently active.
if (cache.isHealthMonitoring()) {
console.log('Health monitoring is active');
} else {
console.log('Health monitoring is inactive');
}โ๏ธ Configuration Options
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:
// 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:
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
undefinedinstead 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:
// 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
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
// Increase timeout for slow systems
const cache = require('persistent-cache')({
lockTimeout: 15000 // 15 seconds
});Performance Tuning
// 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