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 09 Answers
Reset to default 3i 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){}