JSPM

@titansys/persistent-cache

2.0.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q52249F
  • License MIT

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

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 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:

// 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