Open dantehemerson opened 2 years ago
Any update on when will this be completed?
+1
+1
+1
This is in the works. Stay tuned.
Hi, has there been any progress on this?
+1
+1
+1
+1
+1
+1
First of all, thank you all for showing your interest. It encouraged me to finally work on this again.
I am happy to inform you that I have just released v3.0.0 of this package on npm which upgrades the redis dependency to redis@^4.3.1 and adds new TypeScript declarations.
Please let me know if you have any feedback or further requests.
Is it work now for Nest.js ?
@DmytroHaponovMD This can currently be achieved using:
import { redisStore } from 'cache-manager-redis-store';
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
CacheModule.register({
// @ts-ignore
store: async () => await redisStore({
// Store-specific configuration:
socket: {
host: 'localhost',
port: 6379,
}
})
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Unfortunately you are going to need the // @ts-ignore
for now, since the interface does not allow Promise<CacheStore>
to be returned.
@DmytroHaponovMD This can currently be achieved using:
import { redisStore } from 'cache-manager-redis-store'; import { CacheModule, Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ CacheModule.register({ // @ts-ignore store: async () => await redisStore({ // Store-specific configuration: socket: { host: 'localhost', port: 6379, } }) }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
Unfortunately you are going to need the
// @ts-ignore
for now, since the interface does not allowPromise<CacheStore>
to be returned.
this can't work becouse store
field is required for option passed in redisStore function
@DmytroHaponovMD This can currently be achieved using:
import { redisStore } from 'cache-manager-redis-store'; import { CacheModule, Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ CacheModule.register({ // @ts-ignore store: async () => await redisStore({ // Store-specific configuration: socket: { host: 'localhost', port: 6379, } }) }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
Unfortunately you are going to need the
// @ts-ignore
for now, since the interface does not allowPromise<CacheStore>
to be returned.this can't work becouse
store
field is required for option passed in redisStore function
Is it not why // @ts-ignore is there?
@DmytroHaponovMD This can currently be achieved using:
import { redisStore } from 'cache-manager-redis-store'; import { CacheModule, Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ CacheModule.register({ // @ts-ignore store: async () => await redisStore({ // Store-specific configuration: socket: { host: 'localhost', port: 6379, } }) }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
Unfortunately you are going to need the
// @ts-ignore
for now, since the interface does not allowPromise<CacheStore>
to be returned.this can't work becouse
store
field is required for option passed in redisStore functionIs it not why // @ts-ignore is there?
// @ts-ignore works for next line, so effected line is store: async () => await redisStore({
, but error is inside redisStore, there is another store
property sibling of socket
.
@dabroek The DefinitelyTyped typings for this package need to be updated for ^3.0 https://www.npmjs.com/package/@types/cache-manager-redis-store -- this is the root of the error @DmytroHaponovMD is seeing, I believe
This seems to be working for me:
@Module({
imports: [
['true', '1', 'yes'].includes(<string>process.env.API_REDIS_STORE_IS_ACTIVE)
? CacheModule.register({
isGlobal: true,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
store: async () => {
return await redisStore({
// Store-specific configuration:
socket: {
host: process.env.API_REDIS_HOST,
port: +(<string>process.env.API_REDIS_PORT),
},
});
},
})
: CacheModule.register({ isGlobal: true }),
...
With
"cache-manager": "^5.1.1",
"cache-manager-redis-store": "^3.0.1",
I found a workaround to use registerAsync:
import { CacheStore } from '@nestjs/common/cache/interfaces/cache-manager.interface'
CacheModule.registerAsync({
imports: [ConfigModule],
useFactory: async (config: ConfigService) =>
await redisStore({
socket: {
host: config.get('REDIS_HOST'),
port: +config.get('REDIS_PORT'),
},
}) as unknown as CacheStore,
inject: [ConfigService],
}),
Also:
"cache-manager": "^5.1.1",
"cache-manager-redis-store": "^3.0.1",
@assisgui same here but had to also configure the ttl:
CacheModule.registerAsync({
imports: [ConfigModule],
useFactory: async (config: ConfigService) => {
const store = await redisStore({
socket: {
host: config.get('REDIS_HOST'),
port: +config.get('REDIS_PORT'),
},
password: config.get('REDIS_PASSWORD'),
});
return {
store: store as unknown as CacheStore,
ttl: 60 * 60 * 24 * 7,
};
},
inject: [ConfigService],
}),
Any update on when will this be completed?
Using cache-manager '5.1.1' I was getting the following error:
TypeError: store.get is not a function
It worked for me after the cache-manager downgrade version to 4.1.0
@Module({
imports: [
CacheModule.registerAsync({
isGlobal: true,
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: config.get('REDIS_HOST'),
port: +config.get('REDIS_PORT'),
},
password: config.get('REDIS_PASSWORD'),
});
return {
store: store as unknown as CacheStore,
ttl: 5
};
}
})
]
})
export class RedisModule {}
"@nestjs/core": "9.0.11",
"cache-manager": "4.1.0",
"cache-manager-redis-store": "3.0.1",
Using cache-manager '5.1.1' I was getting the following error:
TypeError: store.get is not a function
It worked for me after the cache-manager downgrade version to 4.1.0
@Module({ imports: [ CacheModule.registerAsync({ isGlobal: true, inject: [ConfigService], useFactory: async (configService: ConfigService) => { const store = await redisStore({ socket: { host: config.get('REDIS_HOST'), port: +config.get('REDIS_PORT'), }, password: config.get('REDIS_PASSWORD'), }); return { store: store as unknown as CacheStore, ttl: 5 }; } }) ] }) export class RedisModule {}
"@nestjs/core": "9.0.11", "cache-manager": "4.1.0", "cache-manager-redis-store": "3.0.1",
In my case - it doesn't work, and I do not want to check all time is here fix or not. So, the question is still actual:
Any update on when will this be completed?
CacheModule.registerAsync<RedisClientOptions>({
isGlobal: true,
imports: [SharedModule],
inject: [ApiConfigService],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: config.get('REDIS_HOST'),
port: +config.get('REDIS_PORT'),
},
password: config.get('REDIS_PASSWORD'),
});
return {
store: {
create: () => store as unknown as CacheStore,
},
ttl: 60 * 60 * 24 * 7, // 1 week
};
},
}),
works fine for me, just copy and use above code :)
Hi @dabroek, any news for the Type, my repo not allow ts ignore lol
Just make a PR to this repository, so you can use new typings https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cache-manager-redis-store
I have used the example code above but it seems that Nestjs does not use Redis and use in-memory cache instead.
@assisgui same here but had to also configure the ttl:
CacheModule.registerAsync({ imports: [ConfigModule], useFactory: async (config: ConfigService) => { const store = await redisStore({ socket: { host: config.get('REDIS_HOST'), port: +config.get('REDIS_PORT'), }, password: config.get('REDIS_PASSWORD'), }); return { store: store as unknown as CacheStore, ttl: 60 * 60 * 24 * 7, }; }, inject: [ConfigService], }),
Here is my versions
"cache-manager": "^5.1.3",
"cache-manager-redis-yet": "^4.0.0",
"@nestjs/common": "^9.2.0",
"redis": "^4.4.0",
I think caching factory function detects 2 types of store
property as shown here
create
function.So, what I have tried is to return an object CacheStoreFactory
with create
function, which returns the store
object and it work!
CacheModule.registerAsync<RedisClientOptions>({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
},
});
return {
store: {
create: () => store,
},
};
},
inject: [ConfigService],
})
Thanks @ntchjb mine is now started to use Redis instead in-memory cache, but ttl is not working idk whether it is only me or everyone also experience the same stuff, I only managed to get it working by using the @CacheTTL() decorator
Hello, I came here across the nestjs cache docs. Thanks to @ntchjb, I could set the Redis to my cache store, but even though, the ttl option had not worked. So I have tried to give the ttl option to redisStore function argument. Then, It works!
CacheModule.registerAsync<RedisClientOptions>({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
},
});
return {
store: {
create: () => store,
},
};
},
inject: [ConfigService],
})
import { ConfigModule, ConfigService } from '@nestjs/config';
import { redisStore } from 'cache-manager-redis-store';
export const RedisClientConfig = {
isGlobal: true,
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
},
ttl: 60,
});
return {
store: () => store,
};
},
inject: [ConfigService],
};
One regretful thing is that the ttl option is not applied when using cache manager's set method by injecting cache-manager in *.service.ts. Fortunately, the @CacheTTL() decorate is working.
Here's my version
"@nestjs/common": "^9.2.0",
"@nestjs/config": "^2.2.0",
"cache-manager": "^5.1.3",
"cache-manager-redis-store": "^3.0.1",
"redis": "^4.5.0",
This is how I have solved it:
import { Global, Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { redisStore } from 'cache-manager-redis-store';
export const REDIS_CACHE = 'REDIS_CACHE';
@Global()
@Module({
imports: [ConfigModule],
providers: [
{
provide: REDIS_CACHE,
useFactory: async (configService: ConfigService) => await redisStore({
socket: {
host: configService.get('REDIS_HOST'),
port: +configService.get('REDIS_PORT')
},
ttl: 10
})
,
inject: [ConfigService]
}
],
exports: [REDIS_CACHE]
})
export class RedisCacheModule {
}
One regretful thing is that the ttl option is not applied when using cache manager's set method by injecting cache-manager in *.service.ts. Fortunately, the @CacheTTL() decorate is working.
It seems like set method expects ttl option as an object value not a number, which is misled by type definition.
It works after I changed like below.
this.cacheManager.set("key", "value", { ttl: 10 } as any);
version
"cache-manager": "^5.1.3",
"cache-manager-redis-store": "^3.0.1",
Tried this configuration, and checked that redisStore connects to redis by MONITOR
command in redis, but does not save data or retrieve data from it. I dunno why...
@Module({
imports: [
PrismaModule,
CacheModule.registerAsync<CacheModuleAsyncOptions>({
useFactory: async () => {
const store = await redisStore({
socket: {
tls: true,
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
passphrase: process.env.REDIS_PASS,
rejectUnauthorized: process.env.NODE_ENV === 'production',
},
database: Number(process.env.REDIS_TOKEN_DB),
password: process.env.REDIS_PASS,
});
return {
store,
};
},
}),
],
controllers: [TokenController],
providers: [TokenService],
})
export default class TokenModule {}
Can anyone please share the updated, working code with the modules & versions ?
And also please help on how to connect to redis cluster with auth ? (AWS ElastiCache)
I have this, and it works
@Module({
imports: [
ConfigModule,
CacheModule.registerAsync<any>({
isGlobal: true,
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const options = await configService.getRedisOptions();
const store = await redisStore({
socket: { host: options.host, port: options.port },
ttl: 60,
});
return {
store: () => store,
};
},
inject: [ConfigService],
}),
],
exports: [ConfigModule],
})
export class CommonModule {}
@codeprefect Could you please share the below dependencies versions from your package.json ?
"cache-manager"
"cache-manager-redis-store"
"redis"
"@nestjs/core"
And also please let me know if the above code works for AWS ElastiCache CLUSTER with authorization, because the above code doesn't specify any of that.
Hey @kamal-brill , This should work for you.
const store = await redisStore({
socket: { host: <your host>, port: <your port> },
username: <username, usually (default)>,
password: <password>,
database: <redis database (0 - 15)>,
})
I tested it with a redislabs instance.
One regretful thing is that the ttl option is not applied when using cache manager's set method by injecting cache-manager in *.service.ts. Fortunately, the @CacheTTL() decorate is working.
It seems like set method expects ttl option as an object value not a number, which is misled by type definition.
It works after I changed like below.
this.cacheManager.set("key", "value", { ttl: 10 } as any);
version
"cache-manager": "^5.1.3", "cache-manager-redis-store": "^3.0.1",
I have also confirmed this issue.
One regretful thing is that the ttl option is not applied when using cache manager's set method by injecting cache-manager in *.service.ts. Fortunately, the @CacheTTL() decorate is working.
It seems like set method expects ttl option as an object value not a number, which is misled by type definition. https://github.com/dabroek/node-cache-manager-redis-store/blob/04d04cb5e5a472a9f8eb78c59fa1f90eb6df5839/index.js#L19
It works after I changed like below.
this.cacheManager.set("key", "value", { ttl: 10 } as any);
version
"cache-manager": "^5.1.3", "cache-manager-redis-store": "^3.0.1",
I have also confirmed this issue.
I trace the code, the default ttl been controlled by "cacheManager". The object has a ttl function on element "store" like sceenshot as following. So, if we set ttl as sample, every thing will be fine!
CacheModule.registerAsync<any>({
isGlobal: true,
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
socket: {
host: 'localhost',
port: 6379
},
ttl: 5000
} as any);
return {
store: () => store,
};
}
}),
my version
"cache-manager": "^5.1.4",
"cache-manager-redis-store": "^3.0.1",
One regretful thing is that the ttl option is not applied when using cache manager's set method by injecting cache-manager in *.service.ts. Fortunately, the @CacheTTL() decorate is working.
It seems like set method expects ttl option as an object value not a number, which is misled by type definition.
It works after I changed like below.
this.cacheManager.set("key", "value", { ttl: 10 } as any);
version
"cache-manager": "^5.1.3", "cache-manager-redis-store": "^3.0.1",
This is the only solution that worked for me.
Since the issue is still active, and there's no clear solution posted, allow me to provide a clean fix:
Author of the original node-cache-manager library has forked this client and adapted the required fixes. It is compatible with latest versions of cache-manager and redis libraries. Replace this library with cache-manager-redis-yet
and you're good to go.
The rest of the comment is only relevant for NestJS users.
Install cache-manager-redis-yet
using your package manager.
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { redisStore } from 'cache-manager-redis-yet';
@Module({
imports: [
CacheModule.registerAsync({
useFactory: async () => ({
store: await redisStore({ ttl: 5000 }),
}),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
You can extend on this to provide the required connection credentials to await redisStore()
from config
, just follow NestJS docs.
ttl
to await redisStore({ ttl: 5000 })
. Setting ttl
next to store
doesn't work. Also, NestJS' default 5s TTL doesn't apply when using redisStore
— provide it manually as illustrated.@CacheTTL(x)
doesn't currently work, because of another change in cache-manager 5. I've provided a workaround that you can use until this is fixed on NestJS side. Same thing applies, use milliseconds instead of seconds with CacheTTL.Warning Make sure you're using NestJS v 9.2+, since there was another issue with cache-manager 5 that was recently fixed.
Note If you found this helpful, please add reaction instead of writing a new comment, so this doesn't get lost in the thread. Thanks 🙏
Since the issue is still active, and there's no clear solution posted, allow me to provide a clean fix:
Author of the original node-cache-manager library has forked this client and adapted the required fixes. It is compatible with latest versions of cache-manager and redis libraries. Replace this library with
cache-manager-redis-yet
and you're good to go.The rest of the comment is only relevant for NestJS users.
How to use redis with NestJS cache manager
Install
cache-manager-redis-yet
using your package manager.import { CacheModule, Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { redisStore } from 'cache-manager-redis-yet'; @Module({ imports: [ CacheModule.registerAsync({ useFactory: async () => ({ store: await redisStore({ ttl: 5000 }), }), }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
You can extend on this to provide the required connection credentials to
await redisStore()
fromconfig
, just follow NestJS docs.Notes about TTL
- cache-manager v4 was using seconds for TTL, cache-manager v5 has switched to milliseconds. Use milliseconds where NestJS docs say seconds.
- you have to provide your default
ttl
toawait redisStore({ ttl: 5000 })
. Settingttl
next tostore
doesn't work. Also, NestJS' default 5s TTL doesn't apply when usingredisStore
— provide it manually as illustrated.- Overriding global TTL using
@CacheTTL(x)
doesn't currently work, because of another change in cache-manager 5. I've provided a workaround that you can use until this is fixed on NestJS side. Same thing applies, use milliseconds instead of seconds with CacheTTL.Warning Make sure you're using NestJS v 9.2+, since there was another issue with cache-manager 5 that was recently fixed.
Note If you found this helpful, please add reaction instead of writing a new comment, so this doesn't get lost in the thread. Thanks pray
to change
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { redisStore } from 'cache-manager-redis-yet';
@Module({
imports: [
CacheModule.registerAsync({
useFactory: async () => await redisStore({ ttl: 5000 }),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
to fix
this.cacheManager.get(key)
return store.get is not a function
For me it worked with cache-manager-redis-yet
using this config:
useFactory: async () => {
return {
store: await redisStore({
// client options
}),
};
}
Following async configuration working fine for me.
CacheModule.registerAsync<RedisClientOptions>({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
store: redisStore as unknown as CacheStore,
url: `redis://${configService.get<string>('REDIS_HOST')}:${configService.get<number>('REDIS_PORT')}`,
database: configService.get<number>('REDIS_DB'),
ttl: 24 * 60 * 60, // 1 day
}),
isGlobal: true,
})
我想要在docker中使用,但会一直显示redis的自定义配置无效的问题,就像下面这样,无论port
还是host
都仍然使用的默认的:
我是这样解决的,在redisStore
中配置,可以成功,但没有在任何文档中找到这样的配置,不知道是否符合实践:
CacheModule.registerAsync<RedisClientOptions>({
isGlobal: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
store: await redisStore({
ttl: 5000,
url: `redis://${configService.get<string>(
'REDIS_HOST'
)}:${configService.get<number>('REDIS_PORT')}`,
}),
}),
}),
this works for me with the latest package versions:
CacheModule.register({
store: async () =>
await redisStore({
socket: {
host: 'localhost',
port: 6379,
},
ttl: 10000,
}),
isGlobal: true,
})
@assisgui same here but had to also configure the ttl:
CacheModule.registerAsync({ imports: [ConfigModule], useFactory: async (config: ConfigService) => { const store = await redisStore({ socket: { host: config.get('REDIS_HOST'), port: +config.get('REDIS_PORT'), }, password: config.get('REDIS_PASSWORD'), }); return { store: store as unknown as CacheStore, ttl: 60 * 60 * 24 * 7, }; }, inject: [ConfigService], }),
This seems to work with latest packages, the former left the TTL to -1. Noticed cached items didn't expire and checked the database.
CacheModule.registerAsync({
imports: [ConfigModule],
useFactory: async (config: ConfigService) => {
const store = await redisStore({
socket: {
host: config.get<string>('REDIS_HOST'),
port: config.get<number>('REDIS_PORT'),
},
password: config.get<string>('REDIS_PASSWORD'),
ttl: 60, // 60 seconds
});
return {
store: store as unknown as CacheStore,
};
},
inject: [ConfigService],
}),
"@nestjs/cache-manager": "^1.0.0",
"@nestjs/common": "^9.0.0",
"redis": "^4.6.6",
"cache-manager-redis-store": "^3.0.1",
This is my solution, works with latest version:
import { RedisClientOptions } from 'redis';
import { redisStore } from 'cache-manager-redis-yet';
import { ConfigModule, ConfigService } from '@nestjs/config';
CacheModule.registerAsync<RedisClientOptions>({
imports: [ConfigModule],
useFactory: async (config: ConfigService) => ({
store: await redisStore({ url: config.get<string>('REDIS_URL') })
}),
inject: [ConfigService]
}),
"@nestjs/common": "^9.0.11",
"cache-manager": "^4.1.0",
"cache-manager-redis-yet": "^4.1.1",
"redis": "^4.6.7",
It's also important to note that if you'll be importing this cache module from within app.module.ts
, you have to set isGlobal
to true
To use newest types features for typescript and avoid errors with types when using latest 3.x versions