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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@onlineapps/conn-base-cache

v1.0.8

Published

Redis cache connector with TTL, invalidation, and namespace support for OA Drive microservices

Readme

@onlineapps/conn-base-cache

Redis cache connector with TTL, invalidation, and namespace support for OA Drive microservices.

Features

  • 🔑 Automatic key prefixing - All keys use cache: prefix
  • ⏱️ TTL support - Automatic expiration for cached data
  • 🗂️ Namespace isolation - Separate cache spaces per service
  • 📊 Built-in statistics - Hit rate, miss tracking
  • 🔄 Atomic operations - Increment, decrement support
  • 🎯 Pattern invalidation - Delete by wildcard patterns
  • 🔐 Safe namespacing - Never touches obs: monitoring keys
  • 🧪 Mock implementation - For testing

Installation

npm install @onlineapps/conn-base-cache

Quick Start

const CacheConnector = require('@onlineapps/conn-base-cache');

const cache = new CacheConnector({
  host: 'localhost',
  port: 6379,
  defaultTTL: 3600, // 1 hour
  namespace: 'invoice-service'
});

await cache.connect();

// Set value with TTL
await cache.set('user:123', { name: 'John', role: 'admin' }, 600); // 10 min

// Get value
const user = await cache.get('user:123');

// Delete by pattern
await cache.deleteByPattern('user:*');

// Get statistics
console.log(cache.getStats());
// { hits: 1, misses: 0, sets: 1, deletes: 5, errors: 0, hitRate: '100%' }

Configuration

| Option | Environment Variable | Default | Description | |--------|---------------------|---------|-------------| | host | REDIS_HOST | localhost | Redis server host | | port | REDIS_PORT | 6379 | Redis server port | | password | REDIS_PASSWORD | - | Redis password | | db | REDIS_DB | 0 | Redis database number | | defaultTTL | - | 3600 | Default TTL in seconds | | namespace | - | - | Key namespace | | maxRetries | - | 3 | Max connection retries | | retryDelay | - | 100 | Retry delay in ms |

API Reference

Connection Management

connect()

Establish Redis connection.

await cache.connect();

disconnect()

Close Redis connection.

await cache.disconnect();

Basic Operations

get(key)

Get value from cache.

const value = await cache.get('key');
// Returns parsed object or string

set(key, value, ttl?)

Set value in cache with optional TTL.

await cache.set('key', { data: 'value' }, 3600);
// Returns true on success

delete(key)

Delete single key.

await cache.delete('key');
// Returns true if key existed

exists(key)

Check if key exists.

const exists = await cache.exists('key');
// Returns boolean

Pattern Operations

deleteByPattern(pattern)

Delete all keys matching pattern.

const deleted = await cache.deleteByPattern('session:*');
// Returns number of deleted keys

TTL Management

ttl(key)

Get remaining TTL for key.

const seconds = await cache.ttl('key');
// Returns: seconds (-1 if no TTL, -2 if not exists)

expire(key, ttl)

Update TTL for existing key.

await cache.expire('key', 7200); // 2 hours
// Returns true on success

Atomic Operations

incr(key, increment?)

Increment numeric value.

const newValue = await cache.incr('counter', 5);
// Returns new value

decr(key, decrement?)

Decrement numeric value.

const newValue = await cache.decr('counter', 1);
// Returns new value

Batch Operations

mget(keys)

Get multiple values at once.

const values = await cache.mget(['key1', 'key2', 'key3']);
// Returns: { key1: value1, key2: value2, key3: value3 }

mset(keyValues, ttl?)

Set multiple values at once.

await cache.mset({
  'key1': 'value1',
  'key2': { data: 'value2' }
}, 3600);
// Returns true on success

Utility Methods

withNamespace(namespace)

Create namespaced instance.

const userCache = cache.withNamespace('users');
await userCache.set('123', userData);
// Actual key: cache:invoice-service:users:123

wrap(fn, options)

Create cached function (memoization).

const cachedFetch = cache.wrap(async (userId) => {
  return await fetchUserFromDB(userId);
}, {
  ttl: 600,
  keyPrefix: 'user'
});

const user = await cachedFetch(123);
// First call fetches from DB and caches
// Subsequent calls return from cache

flush(confirm)

Clear all cache keys (dangerous!).

await cache.flush(true); // Must confirm with true

getStats()

Get cache statistics.

const stats = cache.getStats();
// { hits: 50, misses: 10, sets: 30, deletes: 5, errors: 0, hitRate: '83.33%' }

healthCheck()

Check Redis connection health.

const healthy = await cache.healthCheck();
// Returns boolean

Usage Patterns

Service-Level Caching

class InvoiceService {
  constructor() {
    this.cache = new CacheConnector({
      namespace: 'invoice-service'
    });
  }

  async getInvoice(id) {
    // Check cache first
    const cached = await this.cache.get(`invoice:${id}`);
    if (cached) return cached;

    // Fetch from database
    const invoice = await db.getInvoice(id);

    // Cache for 1 hour
    await this.cache.set(`invoice:${id}`, invoice, 3600);

    return invoice;
  }

  async invalidateInvoice(id) {
    await this.cache.delete(`invoice:${id}`);
  }
}

API Response Caching

// In service wrapper
async function callApiWithCache(operation, params) {
  const cacheKey = `api:${operation}:${JSON.stringify(params)}`;

  // Try cache
  const cached = await cache.get(cacheKey);
  if (cached) {
    logger.debug('Cache hit for API call');
    return cached;
  }

  // Make API call
  const result = await apiCaller.call(operation, params);

  // Cache result
  await cache.set(cacheKey, result, 300); // 5 minutes

  return result;
}

Session Management

const sessionCache = cache.withNamespace('sessions');

// Store session
await sessionCache.set(sessionId, {
  userId: 123,
  roles: ['admin'],
  createdAt: Date.now()
}, 1800); // 30 minutes

// Refresh session TTL
await sessionCache.expire(sessionId, 1800);

// Clear all sessions for user
await sessionCache.deleteByPattern(`*:user:123`);

Testing

Use the built-in mock for testing:

const { MockCacheConnector } = require('@onlineapps/conn-base-cache');

describe('MyService', () => {
  let cache;

  beforeEach(() => {
    cache = new MockCacheConnector();
  });

  it('should cache results', async () => {
    await cache.set('test', 'value');
    const value = await cache.get('test');
    expect(value).toBe('value');
    expect(cache.getStats().hits).toBe(1);
  });
});

Important Notes

  1. Key Prefixing: All keys automatically get cache: prefix
  2. Namespace Isolation: Use namespaces to avoid key collisions
  3. TTL Best Practices: Always set appropriate TTL to prevent memory issues
  4. Pattern Deletion: Use carefully as it can be expensive on large datasets
  5. Never Access: This connector never touches obs: namespace (monitoring)

Integration with Service Wrapper

class ServiceWrapper {
  constructor(config) {
    this.cache = new CacheConnector({
      namespace: config.serviceName
    });
  }

  async processWorkflow(message) {
    // Cache workflow state
    await this.cache.set(
      `workflow:${message.workflowId}`,
      message,
      600 // 10 minutes
    );
  }
}

Error Handling

All methods throw errors with descriptive messages:

try {
  await cache.get('key');
} catch (error) {
  if (error.message.includes('Cache get failed')) {
    // Handle cache failure
  }
}

Performance Tips

  1. Use mget/mset for batch operations
  2. Enable pipelining for multiple operations
  3. Set appropriate TTL to balance freshness and performance
  4. Use namespaces to organize keys
  5. Monitor hit rate with getStats()

License

MIT