最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - In Nest js, I added Redis as a cache manager. And can't find any added data in Redis after calling the set

programmeradmin1浏览0评论

Node version: v14.15.4 Nest-js version: 9.0.0

app.module.ts Here is the code. In the app module, I am registering Redis as a cache manager.

@Module({
  imports: [
    CacheModule.register({
      isGlobal: true,
      store: redisStore,
      url: process.env.REDIS_URL,
    })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

service.ts The cache data method is for storing data with a key. -> the problem is the set function doesn't save anything

And get Data for returning the data by key.

@Injectable()
export class SomeService {
      constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

      async cacheData(key: string, data): Promise<void> {
        await this.cacheManager.set(key, data);
      }

      async getData(key: string, data): Promise<any> {
        return this.cacheManager.get(key);
      }
}




It doesn't throw any error in runtime.

Node version: v14.15.4 Nest-js version: 9.0.0

app.module.ts Here is the code. In the app module, I am registering Redis as a cache manager.

@Module({
  imports: [
    CacheModule.register({
      isGlobal: true,
      store: redisStore,
      url: process.env.REDIS_URL,
    })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

service.ts The cache data method is for storing data with a key. -> the problem is the set function doesn't save anything

And get Data for returning the data by key.

@Injectable()
export class SomeService {
      constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

      async cacheData(key: string, data): Promise<void> {
        await this.cacheManager.set(key, data);
      }

      async getData(key: string, data): Promise<any> {
        return this.cacheManager.get(key);
      }
}




It doesn't throw any error in runtime.

Share Improve this question edited Aug 3, 2022 at 5:00 Nairi Abgaryan asked Aug 2, 2022 at 20:25 Nairi AbgaryanNairi Abgaryan 6661 gold badge5 silver badges16 bronze badges 0
Add a comment  | 

9 Answers 9

Reset to default 3

i has met the same problem as you,the way to fix this is using the install cmd to change the version of cache-manager-redis-store to 2.0.0 like 'npm i [email protected]'

when you finish this step, the use of redisStore can be found,then the database can be linked.

I would like to add to the response of @Hailgrim which worked for me but I added types validations or casting for typescript and for saving an array of objects. I hope it will be useful!

  • "cache-manager": "^5.2.1"
  • "cache-manager-redis-store": "^2.0.0"
  • "@nestjs/cache-manager": "^1.0.0",
  • "@types/cache-manager-redis-store": "^2.0.1",

redis.module.ts

    import { Module } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CacheModule } from '@nestjs/cache-manager';
import { RedisService } from './redis.service';

const redisModuleFactory = CacheModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    ttl: configService.get('CACHE_TTL'),
    store: redisStore,
    host: configService.get('CACHE_HOST'),
    port: configService.get('CACHE_PORT'),
  }),
  inject: [ConfigService],
});

@Module({
  imports: [redisModuleFactory],
  controllers: [],
  providers: [RedisService],
  exports: [RedisService],
})
export class RedisModule {}

and redis.service.ts

import { CACHE_MANAGER } from '@nestjs/cache-manager';
import {
  Inject,
  Injectable,
  InternalServerErrorException,
  Logger,
} from '@nestjs/common';
import { throws } from 'assert';
import { Cache } from 'cache-manager';

@Injectable()
export class RedisService {
  private logger = new Logger(RedisService.name);
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  async set(key: string, value: unknown): Promise<void> {
    try {
      await this.cacheManager.set(`yourglobalkey::${key}`, value);
    } catch (error) {
      throw new InternalServerErrorException();
    }
  }

  async get<T>(key: string): Promise<T | undefined> {
    try {
      const jsonData: string | undefined = await this.cacheManager.get<string>(
        `yourglobalkey::${key}`,
      );
      return jsonData ? JSON.parse(jsonData!) : undefined;
    } catch (error) {
      throw new InternalServerErrorException();
    }
  }
}

you can call it from outside like... my case an array of objects.

 const countries: yourType[] | undefined = await this.redisService.get<
      yourType[]
    >('yourkey');

The default expiration time of the cache is 5 seconds.

To disable expiration of the cache, set the ttl configuration property to 0:

await this.cacheManager.set('key', 'value', { ttl: 0 });

I had the same problem.

It looks like NestJS v9 incompatible with version 5 of cache-manager. So you need to downgrade to v4 for now, until this issue is resolved: https://github.com/node-cache-manager/node-cache-manager/issues/210

Change your package.json to have this in the dependencies:

"cache-manager": "^4.0.0",` 

Another commenter also suggested lowering the redis cache version.

Set the redis store as redisStore.redisStore (You will get an autocomplete)

CacheModule.register({
  isGlobal: true,
  store: redisStore.redisStore,
  url: process.env.REDIS_URL,
})

I am not sure why your getData function returns Promise<void> have you tried returning Promise<any> or the data type you are expecting e.g. Promise<string>. You could also try adding await.

 async getData(key: string, data): Promise<any> {
    return await this.cacheManager.get(key);
 }

Are you sure that you are connecting to redis successfully ?. Have you tried adding password and tls (true/false) configuration ?

@Module({
  imports: [
    CacheModule.register({
      isGlobal: true,
      store: redisStore,
      url: process.env.REDIS_URL,
      password: process.env.REDIS_PASSWORD,
      tls: process.env.REDIS_TLS
    })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

My stack:

  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]

redis.service.ts:

import {
  CACHE_MANAGER,
  Inject,
  Injectable,
  InternalServerErrorException,
} from '@nestjs/common';
import { Cache } from 'cache-manager';

@Injectable()
export class RedisService {
  constructor(
    @Inject(CACHE_MANAGER)
    private cacheManager: Cache,
  ) {}
  async set(key: string, value: unknown): Promise<void> {
    try {
      await this.cacheManager.set(key, value, 0);
    } catch (error) {
      throw new InternalServerErrorException();
    }
  }

  async get(key: string): Promise<unknown> {
    try {
      return await this.cacheManager.get(key);
    } catch (error) {
      throw new InternalServerErrorException();
    }
  }
}

redis.module.ts:

import { CacheModule, Module } from '@nestjs/common';
import type { RedisClientOptions } from 'redis';
import { redisStore } from 'cache-manager-redis-yet';

import {
  REDIS_HOST,
  REDIS_PORT,
} from 'libs/config';
import { RedisService } from './redis.service';

@Module({
  imports: [
    CacheModule.register<RedisClientOptions>({
      isGlobal: true,
      store: redisStore,
      url: `redis://${REDIS_HOST}:${REDIS_PORT}`,
    }),
  ],
  providers: [RedisService],
  exports: [RedisService],
})
export class RedisModule {}

This code works fine for me.

The following works for me

My stack:

  • "@nestjs/common": "^9.2.1"
  • "cache-manager": "^5.2.0"
  • "cache-manager-redis-store": "^2.0.0"

Registered globally in app.module.ts

import { Module, CacheModule} from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';
@Module({
  imports: [
    CacheModule.registerAsync({
      isGlobal: true,
      useFactory: () => ({
        store: redisStore,
        url: process.env.REDIS_URL,
      }),
    }),
  ]
})

Make sure not to register the CacheModule again in your feature module, or the global one will be overwritten and the app will still use the in-memory cache instead of the Redis instance.

Then you can use the cache manager in your service files.

Not sure if this is correct answer for this question, But if you are facing issue like get or set method not present in the cacheManager error. And

import { Cache } from 'cache-manager';

is not working as well then this is due to new version of the cache manager so currently there is no Cache interface present in the cache-manager, currently it is.

    import { CacheManagerStore } from 'cache-manager';

  constructor(
private readonly prismaservice : PrismaService,
@Inject(CACHE_MANAGER) private cacheManager : CacheManagerStore){}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论