Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@ticatec/redis-client

ticatec158MIT0.2.0TypeScript support: included

A lightweight TypeScript wrapper around ioredis with singleton pattern support, mock Redis for testing, and abstract caching framework.

redis, ioredis, redis-client, mock-redis, typescript, log4js, caching, cache-framework, singleton, json-serialization, ttl, redis-wrapper, data-caching, nodejs

readme

Ticatec Redis Client

中文 | English

Version License: MIT

A lightweight TypeScript wrapper around ioredis, providing convenient methods for Redis operations with singleton pattern support. Features both real Redis connections and mock Redis for testing.

Features

  • Singleton Pattern: Easy-to-use singleton Redis client instance
  • Mock Support: Built-in mock Redis for testing environments
  • TypeScript Support: Full type definitions and IntelliSense support
  • JSON Serialization: Automatic JSON serialization/deserialization for objects
  • Comprehensive Operations: Support for strings, hashes, sets, and lists
  • Caching Framework: Abstract caching data management system
  • Logging Integration: Built-in logging with log4js

Installation

npm install @ticatec/redis-client ioredis ioredis-mock log4js

Quick Start

Basic Usage

import RedisClient from '@ticatec/redis-client';

// Initialize with real Redis
await RedisClient.init({
  host: '127.0.0.1',
  port: 6379,
  // ... other ioredis options
});

const client = RedisClient.getInstance();

// String operations
await client.set('key', 'value', 3600); // with 1-hour TTL
const value = await client.get('key');

// Object operations with JSON serialization
await client.set('user', { name: 'John', age: 30 });
const user = await client.getObject('user');

Testing with Mock Redis

// Initialize with mock Redis (pass null)
await RedisClient.init(null);

const client = RedisClient.getInstance();
await client.set('testKey', 'testValue');
const value = await client.get('testKey');
console.log(value); // 'testValue'

API Reference

Core Methods

String Operations

  • set(key, value, seconds?) - Set key-value pair with optional TTL
  • get(key) - Get value by key
  • getObject(key) - Get and parse JSON object
  • del(key) - Delete key
  • expiry(key, seconds) - Set expiration time

Hash Operations

  • hset(key, data, seconds?) - Set hash fields
  • hget(key, field) - Get hash field value
  • hgetall(key) - Get all hash fields
  • hsetnx(key, field, value) - Set hash field if not exists

Set Operations

  • sadd(key, members, seconds) - Add members to set
  • scard(key) - Get set cardinality
  • isSetMember(key, value) - Check set membership

List Operations

  • rpush(key, data, seconds?) - Push to list tail
  • lrange(key, start, end) - Get list range
  • lrangeObject(key, start, end) - Get list range and parse JSON
  • llen(key) - Get list length
  • lpop(key) - Pop from list head

Caching Framework

The caching framework provides a simple and flexible way to manage cached data with automatic key generation and TTL handling.

AbstractCachedData

Abstract base class for implementing cached data operations. It provides three core methods: load(), save(), and clean():

import { AbstractCachedData, GetKey } from '@ticatec/redis-client';

interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

// Define a user cache using partial keys for flexibility
class UserCache extends AbstractCachedData<User> {
  constructor() {
    // Key generator function accepts partial User object and TTL (1 hour)
    super((key: Partial<User>) => `user:${key.id}`, 3600);
  }

  // Custom method to get user data with caching
  async getUser(id: number): Promise<User | null> {
    try {
      // Try to load from cache using partial key
      const cached = await this.load({ id });
      if (cached) {
        return cached;
      }
    } catch (error) {
      console.warn('Cache miss for user:', id);
    }

    // If not in cache, fetch from database
    const user = await this.fetchUserFromDatabase(id);
    if (user) {
      // Save to cache - the getKey function will extract id from user object
      await this.save(user);
    }

    return user;
  }

  // Custom method to update user data
  async updateUser(id: number, userData: Partial<User>): Promise<void> {
    // Update in database
    const updatedUser = await this.updateUserInDatabase(id, userData);

    // Update cache with new data
    if (updatedUser) {
      await this.save(updatedUser);
    }
  }

  // Custom method to invalidate user cache
  async invalidateUser(id: number): Promise<void> {
    await this.clean({ id });
  }

  private async fetchUserFromDatabase(id: number): Promise<User | null> {
    // Your database logic here
    return null;
  }

  private async updateUserInDatabase(id: number, userData: Partial<User>): Promise<User | null> {
    // Your database update logic here
    return null;
  }
}

CachedDataManager

Singleton manager for registering and retrieving caching instances:

import { CachedDataManager } from '@ticatec/redis-client';

// Initialize the manager
const manager = CachedDataManager.getInstance();

// Create and register cache instances
const userCache = new UserCache();
manager.register(UserCache, userCache);

// Retrieve and use cache instances anywhere in your application
const getUserCache = () => manager.get(UserCache);

// Usage in your application
async function handleUserRequest(userId: number): Promise<User | null> {
  const cache = getUserCache();
  if (cache) {
    return await cache.getUser(userId);
  }
  return null;
}

Advanced Usage Patterns

1. Different cache types with various TTLs:

class SessionCache extends AbstractCachedData<{ sessionId: string, data: any }> {
  constructor() {
    super(key => `session:${key.sessionId}`, 1800); // 30 minutes
  }
}

class ConfigCache extends AbstractCachedData<{ key: string, value: any }> {
  constructor() {
    super(key => `config:${key.key}`, 86400); // 24 hours
  }
}

2. Composite keys for complex scenarios:

interface UserPost {
  userId: number;
  postId: number;
  title: string;
  content: string;
}

class UserPostsCache extends AbstractCachedData<UserPost[]> {
  constructor() {
    super(
      (key: { userId: number, page: number }) => 
        `user:${key.userId}:posts:page:${key.page}`,
      3600 // 1 hour
    );
  }

  async getUserPostsPage(userId: number, page: number): Promise<UserPost[]> {
    const key = { userId, page };

    try {
      return await this.load(key);
    } catch (error) {
      // Cache miss, fetch from API
      const posts = await this.fetchPostsFromAPI(userId, page);
      await this.save(posts);
      return posts;
    }
  }

  private async fetchPostsFromAPI(userId: number, page: number): Promise<UserPost[]> {
    // Your API logic here
    return [];
  }
}

Configuration

Redis Configuration

Pass any valid ioredis configuration object:

await RedisClient.init({
  host: 'localhost',
  port: 6379,
  password: 'your-password',
  db: 0,
  retryDelayOnFailover: 100,
  maxRetriesPerRequest: 3,
  lazyConnect: true
});

Logging

The client uses log4js for logging. Configure logging in your application:

import log4js from 'log4js';

log4js.configure({
  appenders: {
    console: { type: 'console' }
  },
  categories: {
    default: { appenders: ['console'], level: 'info' },
    RedisClient: { appenders: ['console'], level: 'debug' }
  }
});

Error Handling

The client provides built-in error handling and logging:

  • Connection errors are logged automatically
  • JSON parsing errors are handled gracefully
  • Redis command errors are propagated to the caller

Best Practices

  1. Initialize once: Call RedisClient.init() only once in your application
  2. Use mock for tests: Always use init(null) for unit tests
  3. Handle JSON carefully: Use getObject() for JSON data, get() for strings
  4. Set appropriate TTLs: Always consider setting expiration times for cached data
  5. Use caching framework: Extend AbstractCachedData for complex caching logic

Dependencies

  • ioredis (^5.3.2): Redis client for Node.js
  • ioredis-mock (^8.9.0): Mock Redis implementation for testing
  • log4js (peer dependency): Logging framework

License

MIT License. See LICENSE file for details.

Contributing

Contributions are welcome! Please submit issues and pull requests to the GitHub repository.

Contact