JSPM

@bts-soft/cache

1.0.3
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 373
    • Score
      100M100P100Q75934F
    • License MIT

    A NestJS Redis cache and utility module providing advanced Redis operations, configuration, and health checks with built-in support for CacheManager and Redis client.

    Package Exports

    • @bts-soft/cache
    • @bts-soft/cache/dist/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 (@bts-soft/cache) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    @bts-soft/cache

    A lightweight and flexible Redis-based caching package for NestJS applications.
    It provides an easy way to integrate Redis caching, manage keys, handle lists, and use advanced features like distributed locks and scoring systems.


    Features

    • Simple Redis integration for NestJS

    • Cache management with TTL support

    • Key and list utilities for structured Redis data

    • Distributed locking support for concurrency control

    • Easy configuration via environment variables

    • Compatible with NestJS dependency injection


    Installation

    npm install @bts-soft/cache

    Or using Yarn:

    yarn add @bts-soft/cache

    Make sure you have a Redis instance running locally or remotely.


    Setup in NestJS

    Register the cache module globally in your NestJS application.

    import { CacheModule } from '@nestjs/cache-manager';
    import { Module } from '@nestjs/common';
    import { RedisConfigService } from '@bts-soft/cache';
    
    @Module({
      imports: [
        CacheModule.registerAsync({
          useClass: RedisConfigService,
          isGlobal: true,
        }),
      ],
    })
    export class AppModule {}

    Configuration

    The RedisConfigService reads Redis configuration from environment variables.

    Variable Description Default
    REDIS_HOST Redis host address localhost
    REDIS_PORT Redis port number 6379
    REDIS_TTL Default cache TTL (sec) 3600 (1 hour)

    Example .env file:

    REDIS_HOST=localhost
    REDIS_PORT=6379
    REDIS_TTL=3600

    Usage Example

    Basic Caching

    import { Injectable } from '@nestjs/common';
    import { RedisService } from '@bts-soft/cache';
    
    @Injectable()
    export class ExampleService {
      constructor(private readonly redisService: RedisService) {}
    
      async getCachedValue(key: string): Promise<any> {
        const cached = await this.redisService.get(key);
        if (cached) return cached;
    
        const data = await this.fetchFromDatabase();
        await this.redisService.set(key, data, 3600); // cache for 1 hour
        return data;
      }
    
      private async fetchFromDatabase() {
        return { message: 'Hello from DB' };
      }
    }

    List and Score Utilities

    The package supports managing list-based structures and scoring systems via constants.

    Example constants:

    export enum ListConstant {
      CAMPAIGNS = 'campaigns',
      USERS = 'users',
    }
    
    export enum SCORE {
      HIGH = 100,
      MEDIUM = 50,
      LOW = 10,
    }

    Example usage:

    await this.redisService.addToList(ListConstant.CAMPAIGNS, campaignId);
    await this.redisService.setScore('user:123', SCORE.HIGH);

    Distributed Lock Example

    async handleCriticalSection(): Promise<void> {
      const lockKey = 'critical:process';
      const lock = await this.redisService.acquireLock(lockKey, 5000); // 5 seconds
    
      if (!lock) {
        throw new Error('Could not acquire lock');
      }
    
      try {
        // safely perform critical logic
      } finally {
        await this.redisService.releaseLock(lockKey);
      }
    }

    API Reference

    RedisService

    Method Description
    get(key: string) Get a value by key
    set(key: string, value: any, ttl?: number) Set a value with optional TTL
    delete(key: string) Delete a key
    addToList(list: string, value: any) Add a value to a Redis list
    removeFromList(list: string, value: any) Remove a value from a Redis list
    acquireLock(key: string, ttl: number) Acquire a distributed lock
    releaseLock(key: string) Release a distributed lock

    Example Integration

    In your main application entry point (main.ts):

    import * as graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.js';
    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
    
      app.use(graphqlUploadExpress({ maxFileSize: 1000000, maxFiles: 2 }));
    
      await app.listen(3000);
    }
    bootstrap();

    Logging

    The RedisService uses NestJS Logger internally for error tracking and debugging.
    Make sure your application logger is configured to view Redis logs if needed.


    2. Advanced Data Structure Usage

    Your RedisService supports native Redis data structures, which is a major advantage.

    Hash Maps (HSET)

    Used for storing fields and values within a single key, ideal for user profiles or large objects.

    async updateUserInfo(userId: string, key: string, value: any) {
      // Sets a field in the hash map: 'user:123' { "email": "..." }
      await this.redisService.hSet(`user:${userId}`, key, value); 
    }
    
    async getUserFields(userId: string) {
      // Retrieves all fields and values from the hash map, automatically parsed
      return this.redisService.hGetAll(`user:${userId}`);
    }

    Sorted Sets (ZADD)

    Used for leaderboards, ranking, or time-series data.

    // Add user to a leaderboard with a score
    await this.redisService.zAdd('global:leaderboard', 1500, 'user:A'); 
    await this.redisService.zAdd('global:leaderboard', 2200, 'user:B'); 
    
    // Get the top 10 users (reverse range based on score)
    const topUsers = await this.redisService.zRevRange('global:leaderboard', 0, 9);

    Distributed Locking

    Essential for ensuring only one instance of a worker or microservice processes a task (using SET NX PX and Lua scripts).

    const lockKey = `job:process:${jobId}`;
    const lockValue = Math.random().toString();
    const ttlMs = 5000; // Lock for 5 seconds
    
    // Try to acquire the lock
    const acquired = await this.redisService.acquireLock(lockKey, lockValue, ttlMs);
    
    if (acquired) {
      try {
        // Process the task...
      } finally {
        // Release the lock only if we are the owner
        await this.redisService.releaseLock(lockKey, lockValue);
      }
    }

    Pub/Sub (Publish/Subscribe)

    Used for real-time communication between services without polling.

    TypeScript

    // Service A (Publisher)
    await this.redisService.publish('user_events', { type: 'USER_CREATED', id: 456 });
    
    // Service B (Subscriber)
    this.redisService.subscribe('user_events', (message, channel) => {
      console.log(`Received event on ${channel}:`, message);
      // message is already parsed JSON thanks to the wrapper
    });

    Core Features Summary

    Category Methods Provided (Examples) Underlying Redis Structure
    Basic Caching set, get, del, update Key-Value (Standard)
    String Operations incr, decr, append, strlen String
    Hash Maps hSet, hGet, hGetAll, hDel, hIncrBy Hash
    Sets sAdd, sRem, sMembers, sInter Set
    Sorted Sets zAdd, zRange, zScore, zIncrBy Sorted Set
    Lists/Queues lPush, rPush, lPop, lRange List
    Transactions multiExecute, watch, withTransaction Multi, Exec, Watch
    Distributed Locks acquireLock, releaseLock, waitForLock Lua Scripting, SET NX PX
    Utilities exists, ttl, expire Utility Commands
    Messaging publish, subscribe, unsubscribe Pub/Sub
    Geospatial geoAdd, geoPos, geoDist Geospatial (ZSET)

    License

    This package is licensed under the MIT License.

    Contact

    Author: Omar Sabry  

    Email: omar.sabry.dev@gmail.com  

    LinkedIn: Omar Sabry  

    Portfolio: Portfolio


    Repository

    GitHub: Github Repo