Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to manage retry_strategy in store ? #33

Open
lakshmipriyamukundan opened this issue Jul 28, 2021 · 1 comment
Open

How to manage retry_strategy in store ? #33

lakshmipriyamukundan opened this issue Jul 28, 2021 · 1 comment

Comments

@lakshmipriyamukundan
Copy link


@HappyHappy1996
Copy link

HappyHappy1996 commented Oct 28, 2022

this is how I do this with cache-manager-redis-store of version 2:

// `redis-cache.module.ts` file
import {
  CacheModule,
  CACHE_MANAGER,
  Inject,
  Logger,
  Module,
  OnModuleDestroy,
} from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import type { ClientOpts } from 'redis';
import { Cache } from 'cache-manager';

import { RedisCacheStoreProvider } from './redis-cache-store.provider';

@Module({
  imports: [
    ConfigModule,
    CacheModule.registerAsync<ClientOpts>({
      imports: [RedisCacheModule],
      useFactory: async (redisCacheStoreProvider: RedisCacheStoreProvider) => {
        return {
          store: await redisCacheStoreProvider.build(),
        };
      },
      inject: [RedisCacheStoreProvider],
      isGlobal: true,
    }),
  ],
  providers: [RedisCacheStoreProvider],
  exports: [RedisCacheStoreProvider],
})
export class RedisCacheModule implements OnModuleDestroy {
  private readonly logger: Logger = new Logger(RedisCacheModule.name);

  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  onModuleDestroy(): void {
    this.logger.log('Closing Redis cache connection');
    const client = this.cacheManager.store.getClient();
    // https://github.com/nestjs/nest/issues/8020
    client.quit();
  }
}


// ---------------------------------------------------------------------------------------
// `redis-cache-store.provider.ts` file

import redisStore from 'cache-manager-redis-store';
import { Inject, Logger, Injectable } from '@nestjs/common';
import { ConfigType } from '@nestjs/config';

import { redisRetryCallback } from './redis-retry-callback';

import { redisConfig } from 'config';

@Injectable()
export class RedisCacheStoreProvider {
  private readonly logger = new Logger(RedisCacheStoreProvider.name);

  constructor(
    @Inject(redisConfig.KEY)
    private config: ConfigType<typeof redisConfig>,
  ) {}

  async build() {
    const store = await redisStore.create({
      host: this.config.host,
      port: this.config.port,
      // https://github.com/node-cache-manager/node-cache-manager/issues/51
      enable_offline_queue: false,
      retryStrategy: redisRetryCallback(this.config, this.logger),
    });

    return store;
  }
}

// ---------------------------------------------------------------------------------------
// `redis-retry-callback.ts` file
import { RetryStrategyOptions } from '@nestjs/microservices/external/redis.interface';
import { Logger } from '@nestjs/common';
import * as Sentry from '@sentry/node';

import { IRedisConfig } from 'config';

interface RedisRetryStrategyOptions
  // in fact `total_retry_time` and `times_connected` properties are given in camelCase notation - idk why
  extends Omit<RetryStrategyOptions, 'total_retry_time' | 'times_connected'> {
  // so we manually override the interface
  totalRetryTime: number;
  timesConnected: number;
}

export const redisRetryCallback =
  (redisConfig: IRedisConfig, logger: Logger) =>
  ({ error, attempt, totalRetryTime, timesConnected }: RedisRetryStrategyOptions) => {
    const { retryDelay, retryAttempts } = redisConfig;

    if (attempt > retryAttempts) {
      logger.error(`Redis connection retry time exhausted`, {
        totalRetryTime,
        timesConnected,
        retryDelay,
        retryAttempts,
      });
      throw new Error('Redis connection retry time exhausted');
    }

    if (error) {
      logger.error(`Redis connection error. Attempt: ${attempt}. Error: ${error}`);
      Sentry.captureMessage('Redis connection error.', {
        extra: {
          attempt,
          totalRetryTime,
          timesConnected,
          retryDelay,
          retryAttempts,
        },
      });
    }
    return retryDelay;
  };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants