npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@pesalink/cache-package

v1.0.25

Published

Shared cache package that allows microservices to set, get and delete cache data

Readme

CacheService

A comprehensive Redis caching service with support for multiple data structures, circuit breaker pattern, and connection pooling. This service provides a singleton pattern implementation with built-in error handling and monitoring capabilities.

Features

  • Singleton Pattern: Ensures single Redis connection instance
  • Circuit Breaker: Protects against Redis failures with automatic recovery
  • Multiple Data Structures: Supports strings, hashes, JSON, lists, and sets
  • Connection Pooling: Configurable concurrency limits and retry strategies
  • Environment Isolation: Automatic key prefixing based on environment
  • Comprehensive Error Handling: Timeout protection and graceful degradation
  • Health Monitoring: Built-in health checks and connection monitoring

Installation

To use the CacheService in your microservice, follow these steps:

npm install @pesalink/cache-package

## Environment Variables

```env
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_USER=username              # Optional
REDIS_PASSWORD=password          # Optional
REDIS_TLS=true                   # Optional, enables TLS
REDIS_CLUSTER=true               # Optional, enables cluster mode
REDIS_MAX_CONCURRENT_OPS=100     # Optional, default: 100
REDIS_CACHE_TIMEOUT=10000        # Optional, default: 10000ms
NODE_ENV=production              # Optional, used for key prefixing
ENVIRONMENT=production           # Alternative to NODE_ENV

Usage

Basic Setup

const CacheService = require('./CacheService');

// Get singleton instance
const cache = CacheService.getInstance();

// Health check
const isHealthy = await cache.healthCheck();
console.log('Redis is healthy:', isHealthy);

Key Building

The service automatically builds environment-prefixed keys from objects:

const keyObj = { userId: 123, type: 'profile' };
// Generates key: "production|type:profile|userId:123"

API Reference

String Methods

getCache(keyObj)

Retrieves cached data stored as JSON string.

const keyObj = { userId: 123, type: 'profile' };
const userData = await cache.getCache(keyObj);
console.log(userData); // null or parsed JSON object

setCache(keyObj, value, expiryInSeconds = 3600)

Stores data as JSON string with optional expiry.

const keyObj = { userId: 123, type: 'profile' };
const userData = { name: 'John', email: '[email protected]' };
await cache.setCache(keyObj, userData, 7200); // 2 hours expiry

Hash Methods

setHashCache(keyObj, hashData, expiryInSeconds?)

Stores data as Redis hash fields.

const keyObj = { userId: 123, type: 'session' };
const sessionData = {
  token: 'abc123',
  lastActive: '2023-01-01T00:00:00Z',
  ipAddress: '192.168.1.1'
};
await cache.setHashCache(keyObj, sessionData, 3600);

getHashCache(keyObj)

Retrieves all fields from a Redis hash.

const keyObj = { userId: 123, type: 'session' };
const sessionData = await cache.getHashCache(keyObj);
console.log(sessionData); // { token: 'abc123', lastActive: '...', ipAddress: '...' }

getHashFields(keyObj, fields)

Retrieves specific fields from a Redis hash.

const keyObj = { userId: 123, type: 'session' };
const fields = ['token', 'lastActive'];
const partialData = await cache.getHashFields(keyObj, fields);
console.log(partialData); // { token: 'abc123', lastActive: '...' }

JSON Methods (Requires RedisJSON Module)

setJsonCache(keyObj, jsonData, expiryInSeconds?)

Stores data using Redis JSON module.

const keyObj = { userId: 123, type: 'preferences' };
const preferences = {
  theme: 'dark',
  notifications: { email: true, sms: false },
  settings: { language: 'en', timezone: 'UTC' }
};
await cache.setJsonCache(keyObj, preferences, 86400); // 24 hours

getJsonCache(keyObj)

Retrieves JSON data from Redis.

const keyObj = { userId: 123, type: 'preferences' };
const preferences = await cache.getJsonCache(keyObj);
console.log(preferences); // Full JSON object

getJsonPaths(keyObj, paths)

Retrieves specific JSON paths.

const keyObj = { userId: 123, type: 'preferences' };
const paths = ['$.theme', '$.notifications.email'];
const partialPrefs = await cache.getJsonPaths(keyObj, paths);

List Methods

pushToList(keyObj, items, expiryInSeconds?, left = false)

Adds items to a Redis list.

const keyObj = { userId: 123, type: 'activity_log' };
const activities = [
  { action: 'login', timestamp: new Date() },
  { action: 'view_profile', timestamp: new Date() }
];

// Push to right (RPUSH)
await cache.pushToList(keyObj, activities, 604800); // 7 days

// Push to left (LPUSH)
await cache.pushToList(keyObj, activities, 604800, true);

getListRange(keyObj, start = 0, stop = -1)

Retrieves items from a Redis list.

const keyObj = { userId: 123, type: 'activity_log' };

// Get all items
const allActivities = await cache.getListRange(keyObj);

// Get first 10 items
const recentActivities = await cache.getListRange(keyObj, 0, 9);

// Get last 5 items
const lastActivities = await cache.getListRange(keyObj, -5, -1);

Set Methods

addToSet(keyObj, items, expiryInSeconds?)

Adds items to a Redis set.

const keyObj = { userId: 123, type: 'viewed_products' };
const productIds = [101, 102, 103, 104];
await cache.addToSet(keyObj, productIds, 2592000); // 30 days

getSetMembers(keyObj)

Retrieves all members from a Redis set.

const keyObj = { userId: 123, type: 'viewed_products' };
const viewedProducts = await cache.getSetMembers(keyObj);
console.log(viewedProducts); // [101, 102, 103, 104]

Utility Methods

getCachedData(cacheKey, dbFetchMethod, expiryInSeconds = 3600)

Implements cache-aside pattern with automatic fallback.

const keyObj = { userId: 123, type: 'profile' };

const userData = await cache.getCachedData(
  keyObj,
  async () => {
    // This function runs only if cache miss
    return await database.getUserProfile(123);
  },
  7200 // 2 hours cache
);

deleteCache(keyObj)

Deletes cached data.

const keyObj = { userId: 123, type: 'profile' };
await cache.deleteCache(keyObj);

invalidateCache(keyObj)

Alias for deleteCache().

const keyObj = { userId: 123, type: 'profile' };
await cache.invalidateCache(keyObj);

healthCheck()

Performs Redis health check.

const isHealthy = await cache.healthCheck();
if (!isHealthy) {
  console.error('Redis is not responding');
}

disconnect()

Gracefully closes Redis connection.

await cache.disconnect();

Error Handling

The service includes comprehensive error handling:

  • Circuit Breaker: Automatically opens when Redis is unreachable
  • Operation Timeouts: All operations have configurable timeouts
  • Retry Logic: Built-in retry strategy for connection failures
  • Graceful Degradation: Operations fail fast when circuit is open
try {
  const data = await cache.getCache(keyObj);
} catch (error) {
  if (error.message === 'Redis circuit breaker is open') {
    // Handle circuit breaker state
    console.log('Redis is temporarily unavailable');
  } else if (error.message === 'Redis operation limit reached') {
    // Handle concurrency limit
    console.log('Too many concurrent operations');
  } else {
    // Handle other Redis errors
    console.error('Redis operation failed:', error);
  }
}

Best Practices

1. Key Design

// Good: Hierarchical and descriptive
const keyObj = { 
  service: 'user-service',
  userId: 123, 
  type: 'profile',
  version: 'v1'
};

// Avoid: Generic or unclear keys
const keyObj = { id: 123, data: 'stuff' };

2. Expiration Strategy

// Different TTLs for different data types
await cache.setCache(userProfile, userData, 3600);      // 1 hour
await cache.setCache(sessionData, session, 1800);       // 30 minutes  
await cache.setCache(staticConfig, config, 86400);      // 24 hours

3. Error Handling

// Always handle cache failures gracefully
async function getUserData(userId) {
  try {
    const cached = await cache.getCache({ userId, type: 'profile' });
    if (cached) return cached;
  } catch (error) {
    logger.warn('Cache read failed, falling back to database', error);
  }
  
  // Always have a fallback
  return await database.getUser(userId);
}

4. Monitoring

// Regular health checks
setInterval(async () => {
  const healthy = await cache.healthCheck();
  if (!healthy) {
    // Alert or take corrective action
    logger.error('Redis health check failed');
  }
}, 30000); // Every 30 seconds

Data Structure Selection Guide

| Use Case | Data Structure | Method | |----------|----------------|---------| | Simple key-value | String | getCache(), setCache() | | Object with multiple fields | Hash | getHashCache(), setHashCache() | | Complex nested objects | JSON | getJsonCache(), setJsonCache() | | Ordered collections | List | pushToList(), getListRange() | | Unique collections | Set | addToSet(), getSetMembers() |

Performance Considerations

  • Connection Pooling: Singleton pattern ensures efficient connection usage
  • Concurrent Operations: Configurable limits prevent Redis overload
  • Timeouts: All operations have timeout protection
  • JSON vs Hash vs String: Choose based on access patterns:
    • Use Hash for partial field access
    • Use JSON for complex queries and updates
    • Use String for simple objects

License

This service is part of the PesaLink package ecosystem.