I try to implement nestjs backend and redis as caching. I can do it according to the official document https://docs.nestjs.com/techniques/caching#in-memory-cache.
I use the package cache-manager-redis-store
and the code in app.module.ts
is as shown below.
import { Module, CacheModule } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as redisStore from 'cache-manager-redis-store';
import * as Joi from 'joi';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
CacheModule.registerAsync({
imports: [
ConfigModule.forRoot({
validationSchema: Joi.object({
REDIS_HOST: Joi.string().default('localhost'),
REDIS_PORT: Joi.number().default(6379),
REDIS_PASSWORD: Joi.string(),
}),
}),
],
useFactory: async (configService: ConfigService) => ({
store: redisStore,
auth_pass: configService.get('REDIS_PASSWORD'),
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
ttl: 0,
}),
inject: [ConfigService],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
With this setting, I can use get
and set
as expected but I want to use other redis command such as hget
and zadd
. Unfortunately, I cannot find the guide anywhere.
I think there must be a way since cache-manager-redis-store
package said that it just passing the configuration to the underlying node_redis
package. And node-redis
package can use those fancy redis commands.
Would be appreciated if you have solutions.
Thank you both Micael Levi and Hamidreza Vakilian for the help. I did more research and found my solution so I will share it for other people have the same problem.
It seem cache-manager-redis-store
allow only normal redis operation and if you want to use more, you have to access cacheManager.store.getClient()
as Micael suggest.
Cache
interface got no getClient
but RedisCache
had! The problem is RedisCache
interface inside cache-manager-redis-store
package don't export those interface for outsider.
The easiest way to fix this is to create redis.interface.ts
or whatever name for your own.
import { Cache, Store } from 'cache-manager';
import { RedisClient } from 'redis';
export interface RedisCache extends Cache {
store: RedisStore;
}
export interface RedisStore extends Store {
name: 'redis';
getClient: () => RedisClient;
isCacheableValue: (value: any) => boolean;
}
Now you can replace Cache
with RedisCache
interface.
The usage will be as follows.
import {
CACHE_MANAGER,
Inject,
Injectable,
} from '@nestjs/common';
import { RedisClient } from 'redis';
import { RedisCache } from './interface/redis.interface';
@Injectable()
export class RedisService {
private redisClient: RedisClient;
constructor(@Inject(CACHE_MANAGER) private cacheManager: RedisCache) {
this.redisClient = this.cacheManager.store.getClient();
}
hgetall() {
this.redisClient.hgetall('mykey', (err, reply) => {
console.log(reply);
})
}
}
Note that these redisClient
commands do not return value so you have to use callback to get the value.
As you can see that the answer is in callback structure, I prefer await
and async
more so I did a little more work.
import {
BadRequestException,
CACHE_MANAGER,
Inject,
Injectable,
} from '@nestjs/common';
import { RedisClient } from 'redis';
import { RedisCache } from './interface/redis.interface';
@Injectable()
export class RedisService {
private redisClient: RedisClient;
constructor(@Inject(CACHE_MANAGER) private cacheManager: RedisCache) {
this.redisClient = this.cacheManager.store.getClient();
}
async hgetall(key: string): Promise<{ [key: string]: string }> {
return new Promise<{ [key: string]: string }>((resolve, reject) => {
this.redisClient.hgetall(key, (err, reply) => {
if (err) {
console.error(err);
throw new BadRequestException();
}
resolve(reply);
});
});
}
}
By using promise, I can get the answer as if the function return. The usage is as follows.
import { Injectable } from '@nestjs/common';
import { RedisService } from './redis.service';
@Injectable()
export class UserService {
constructor(private readonly redisService: RedisService) {}
async getUserInfo(): Promise<{ [key: string]: string }> {
const userInfo = await this.redisService.hgetall('mykey');
return userInfo;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With