CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-midwayjs--redis

Redis component for Midway.js framework providing comprehensive Redis database integration with support for single instances, clusters, and sentinel configurations

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

redis-service.mddocs/

Redis Service

The RedisService provides the primary interface for Redis operations in Midway.js applications through dependency injection. It wraps the default Redis client instance and delegates all ioredis methods, providing seamless access to Redis functionality.

Capabilities

RedisService Class

Main service wrapper implementing the full Redis interface through method delegation.

/**
 * Primary Redis service for dependency injection
 * Implements the full ioredis Redis interface
 * Automatically connects to the default Redis client
 */
class RedisService implements Redis {
  @Inject()
  private serviceFactory: RedisServiceFactory;
  
  private instance: Redis;
  
  @Init()
  async init(): Promise<void>;
  
  defineCommand(
    name: string,
    definition: {
      lua: string;
      numberOfKeys?: number;
      readOnly?: boolean;
    }
  ): void;
}

interface RedisService extends Redis {}

Service Initialization

Automatically initializes with the default Redis client from the service factory.

/**
 * Initializes the service with default Redis client
 * Called automatically by Midway.js during dependency injection
 * @throws MidwayCommonError if default Redis instance not found
 */
async init(): Promise<void>;

Custom Command Definition

Defines custom Redis commands using Lua scripts.

/**
 * Defines a custom Redis command using Lua scripting
 * The command becomes available as a method on the service
 * @param name - Name of the custom command
 * @param definition - Command definition with Lua script
 */
defineCommand(
  name: string,
  definition: {
    lua: string;
    numberOfKeys?: number;
    readOnly?: boolean;
  }
): void;

Usage Examples:

import { RedisService } from "@midwayjs/redis";
import { Inject, Provide } from "@midwayjs/core";

@Provide()
export class CacheService {
  @Inject()
  redisService: RedisService;

  async init() {
    // Define a custom atomic increment with expire command
    this.redisService.defineCommand('incrWithExpire', {
      lua: `
        local current = redis.call('INCR', KEYS[1])
        if current == 1 then
          redis.call('EXPIRE', KEYS[1], ARGV[1])
        end
        return current
      `,
      numberOfKeys: 1,
      readOnly: false,
    });
  }

  async incrementCounter(key: string, expireSeconds: number) {
    // Use the custom command (TypeScript may need type assertion)
    return (this.redisService as any).incrWithExpire(key, expireSeconds);
  }
}

Redis Operations

The RedisService implements the complete ioredis interface, providing access to all Redis commands and operations:

String Operations

// All string operations from ioredis are available
await redisService.set('key', 'value');
await redisService.get('key');
await redisService.setex('key', 60, 'value'); // Set with expiration
await redisService.incr('counter');
await redisService.mget(['key1', 'key2', 'key3']);

Hash Operations

await redisService.hset('user:123', 'name', 'John');
await redisService.hget('user:123', 'name');
await redisService.hmset('user:123', { name: 'John', age: 30 });
await redisService.hgetall('user:123');

List Operations

await redisService.lpush('queue', 'task1');
await redisService.rpop('queue');
await redisService.lrange('queue', 0, -1);

Set Operations

await redisService.sadd('tags', 'redis', 'database');
await redisService.smembers('tags');
await redisService.sismember('tags', 'redis');

Sorted Set Operations

await redisService.zadd('leaderboard', 100, 'player1');
await redisService.zrange('leaderboard', 0, 9);
await redisService.zrevrange('leaderboard', 0, 9, 'WITHSCORES');

Key Management

await redisService.exists('key');
await redisService.expire('key', 3600);
await redisService.ttl('key');
await redisService.del('key1', 'key2');
await redisService.keys('pattern*');

Usage Examples

Basic Operations

import { RedisService } from "@midwayjs/redis";
import { Inject, Provide } from "@midwayjs/core";

@Provide()
export class UserService {
  @Inject()
  redisService: RedisService;

  async cacheUser(userId: string, userData: any) {
    const key = `user:${userId}`;
    await this.redisService.setex(key, 3600, JSON.stringify(userData));
  }

  async getUser(userId: string) {
    const key = `user:${userId}`;
    const cached = await this.redisService.get(key);
    return cached ? JSON.parse(cached) : null;
  }

  async deleteUser(userId: string) {
    const key = `user:${userId}`;
    await this.redisService.del(key);
  }
}

Session Management

@Provide()
export class SessionService {
  @Inject()
  redisService: RedisService;

  async createSession(sessionId: string, userData: any, ttlSeconds = 1800) {
    const key = `session:${sessionId}`;
    await this.redisService.setex(key, ttlSeconds, JSON.stringify(userData));
  }

  async getSession(sessionId: string) {
    const key = `session:${sessionId}`;
    const data = await this.redisService.get(key);
    return data ? JSON.parse(data) : null;
  }

  async refreshSession(sessionId: string, ttlSeconds = 1800) {
    const key = `session:${sessionId}`;
    await this.redisService.expire(key, ttlSeconds);
  }

  async destroySession(sessionId: string) {
    const key = `session:${sessionId}`;
    await this.redisService.del(key);
  }
}

Rate Limiting

@Provide()
export class RateLimitService {
  @Inject()
  redisService: RedisService;

  async checkRateLimit(
    identifier: string, 
    maxRequests: number, 
    windowSeconds: number
  ): Promise<{ allowed: boolean; remaining: number }> {
    const key = `rate_limit:${identifier}`;
    const current = await this.redisService.incr(key);
    
    if (current === 1) {
      await this.redisService.expire(key, windowSeconds);
    }
    
    const remaining = Math.max(0, maxRequests - current);
    return {
      allowed: current <= maxRequests,
      remaining
    };
  }
}

Event Handling

The RedisService supports all ioredis event handling:

@Provide()
export class MonitorService {
  @Inject()
  redisService: RedisService;

  async init() {
    // Listen for connection events
    this.redisService.on('connect', () => {
      console.log('Redis connected');
    });

    this.redisService.on('error', (error) => {
      console.error('Redis error:', error);
    });

    this.redisService.on('close', () => {
      console.log('Redis connection closed');
    });
  }
}

Transaction Support

Full support for Redis transactions and pipelines:

async transferBetweenCounters(from: string, to: string, amount: number) {
  const multi = this.redisService.multi();
  multi.decrby(from, amount);
  multi.incrby(to, amount);
  
  const results = await multi.exec();
  return results;
}

// Pipeline for bulk operations
async bulkSet(keyValuePairs: Record<string, string>) {
  const pipeline = this.redisService.pipeline();
  
  Object.entries(keyValuePairs).forEach(([key, value]) => {
    pipeline.set(key, value);
  });
  
  await pipeline.exec();
}

docs

configuration.md

index.md

redis-service.md

service-factory.md

tile.json