Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
346 lines (255 loc) · 7.37 KB

File metadata and controls

346 lines (255 loc) · 7.37 KB
Copy raw file
Download raw file
Outline
Edit and raw actions

Cache Refactoring Summary

Overview

The cache library has been refactored from a single monolithic class into a modular, driver-based architecture with extensive new features and Redis support using Bun's native Redis client.

New Architecture

File Structure

src/
├── cache.ts                  # Legacy synchronous cache (backwards compatible)
├── manager.ts                # New async cache manager with driver abstraction
├── config.ts                 # Configuration constants
├── types.ts                  # Core type definitions
├── index.ts                  # Main exports
├── drivers/
│   ├── types.ts             # Driver interfaces and types
│   ├── memory.ts            # In-memory cache driver
│   ├── redis.ts             # Redis driver (Bun native)
│   └── index.ts             # Driver exports
├── serializers/
│   └── index.ts             # Serialization strategies
└── utils/
    └── index.ts             # Utility classes and functions

Key Features Added

1. Multiple Drivers

  • Memory Driver: Fast in-memory caching (same as before, but async)
  • Redis Driver: Distributed caching using Bun's native Redis client (v1.2.9+)
  • Driver abstraction allows easy addition of new drivers

2. Async API

All operations are now promise-based for consistency and to support external storage drivers:

// Old (still works via legacy Cache class)
cache.set('key', 'value')
const value = cache.get('key')

// New (recommended)
await cache.set('key', 'value')
const value = await cache.get('key')

3. Redis Support

Full Redis support using Bun's native Redis client:

const cache = createCache({
  driver: 'redis',
  url: 'redis://localhost:6379',
  prefix: 'myapp',
})

await cache.set('key', 'value', 3600)

Features:

  • Connection management (auto-reconnect, retries)
  • TLS support
  • Pub/Sub support (via Bun's Redis client)
  • All standard Redis operations
  • Tag support using Redis Sets

4. Tagging System

Organize and invalidate cache by tags:

await cache.set('user:1', userData)
await cache.tag('user:1', ['users', 'active'])

// Get all keys by tag
const userKeys = await cache.getKeysByTag('users')

// Delete all entries with a tag
await cache.deleteByTag('users')

5. Namespaces

Isolate cache data with prefixed namespaces:

const userCache = cache.namespace('users')
const postCache = cache.namespace('posts')

await userCache.set('1', userData)
await postCache.set('1', postData)

// No collision between namespaces

6. Serializers

Multiple serialization strategies:

  • JSON: Default serializer for objects
  • String: Plain text values
  • Number: Numeric values
  • Boolean: Boolean values
  • Buffer: Binary data
  • Auto: Automatically detects and preserves types (Date, RegExp, Set, Map, etc.)
  • MessagePack: Efficient binary serialization (optional dependency)
const cache = createCache({
  driver: 'redis',
  serializer: serializers.auto, // Preserves types
})

await cache.set('date', new Date())
const date = await cache.get<Date>('date')
// date is still a Date instance!

7. Advanced Utilities

Rate Limiting

import { RateLimiter } from '@stacksjs/ts-cache'

const limiter = new RateLimiter(cache, 100, 60)
const result = await limiter.check('user:123')

if (result.limited) {
  console.log('Rate limited!')
}

Distributed Locking

import { CacheLock } from '@stacksjs/ts-cache'

const lock = new CacheLock(cache, 30)
const result = await lock.withLock('resource', async () => {
  // Critical section
  return await performOperation()
})

Memoization

import { memoize } from '@stacksjs/ts-cache'

const memoized = memoize(expensiveFunction, cache, {
  ttl: 60,
  keyGenerator: (a, b) => `sum:${a}:${b}`,
})

Circuit Breaker

import { CircuitBreaker } from '@stacksjs/ts-cache'

const breaker = new CircuitBreaker(cache, 5, 60)
const result = await breaker.execute('api', async () => {
  return await callExternalAPI()
})

Cache Warmer

import { CacheWarmer } from '@stacksjs/ts-cache'

const warmer = new CacheWarmer(cache)
await warmer.warm([
  { key: 'user:1', fetcher: () => getUser(1), ttl: 3600 },
  { key: 'user:2', fetcher: () => getUser(2), ttl: 3600 },
])

Debounced Cache

import { DebouncedCache } from '@stacksjs/ts-cache'

const debounced = new DebouncedCache(cache, 1000)
debounced.set('key', 'value') // Debounced by 1 second

8. Remember Pattern

Laravel-style remember pattern:

const user = await cache.remember('user:1', 60, async () => {
  return await database.getUser(1)
})

const config = await cache.rememberForever('config', async () => {
  return await loadConfig()
})

9. Events

Listen for cache operations:

cache.on('hit', (key, value) => {
  console.log(`Cache hit: ${key}`)
})

cache.on('miss', (key) => {
  console.log(`Cache miss: ${key}`)
})

cache.on('set', (key, value, ttl) => {
  console.log(`Cache set: ${key}`)
})

Backwards Compatibility

The legacy synchronous Cache class is still available:

import { Cache } from '@stacksjs/ts-cache'

const cache = new Cache()
cache.set('key', 'value')
const value = cache.get('key')

Migration Guide

From v0.1.x to v0.2.x

  1. Update imports and initialization:

    Before (v0.1.x):

    import cache from '@stacksjs/ts-cache'

    After (v0.2.x):

    import { createCache } from '@stacksjs/ts-cache'
    const cache = createCache()
  2. Add async/await:

    // Old
    cache.set('key', 'value')
    const value = cache.get('key')
    
    // New
    await cache.set('key', 'value')
    const value = await cache.get('key')
  3. Update configuration (optional):

    const cache = createCache({
      driver: 'memory', // or 'redis'
      stdTTL: 3600,
      // ... other options
    })

Configuration

Memory Driver Options

const cache = createCache({
  driver: 'memory',
  stdTTL: 3600,
  checkPeriod: 600,
  maxKeys: 1000,
  useClones: true,
  deleteOnExpire: true,
  prefix: 'myapp',
})

Redis Driver Options

const cache = createCache({
  driver: 'redis',
  url: 'redis://localhost:6379',
  // Or individual options:
  host: 'localhost',
  port: 6379,
  password: 'secret',
  database: 0,
  connectionTimeout: 5000,
  autoReconnect: true,
  maxRetries: 10,
  tls: false,
  stdTTL: 3600,
  prefix: 'myapp',
  serializer: serializers.json,
})

Testing

Run the examples to test the new features:

bun examples/usage.ts

Performance Notes

  • Memory driver: Same performance as before
  • Redis driver: Uses Bun's native bindings for optimal performance
  • Serialization overhead depends on chosen serializer
  • Auto-serializer adds minimal overhead for type preservation

Future Enhancements

Potential additions for future versions:

  • Database drivers (PostgreSQL, MongoDB, etc.)
  • File system driver
  • More pub/sub features
  • Cache warming strategies
  • Advanced eviction policies (LRU, LFU)
  • Compression support
  • Cache metrics and monitoring

Credits

  • Original node-cache implementation
  • Bun team for native Redis client
  • Community feedback and contributions
Morty Proxy This is a proxified and sanitized view of the page, visit original site.