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

Upgrade redis to v4 #40

Open
dantehemerson opened this issue Apr 20, 2022 · 66 comments
Open

Upgrade redis to v4 #40

dantehemerson opened this issue Apr 20, 2022 · 66 comments

Comments

@dantehemerson
Copy link

To use newest types features for typescript and avoid errors with types when using latest 3.x versions

@sarcastic-verma
Copy link

Any update on when will this be completed?

@vxm5091
Copy link

vxm5091 commented Jun 30, 2022

+1

2 similar comments
@Sravanchittimalla
Copy link

+1

@celianvdb
Copy link

+1

@dabroek
Copy link
Owner

dabroek commented Jul 18, 2022

This is in the works. Stay tuned.

@FoxxMD
Copy link

FoxxMD commented Sep 1, 2022

Hi, has there been any progress on this?

@muratdemirci
Copy link

+1

@FoxxMD FoxxMD mentioned this issue Sep 7, 2022
2 tasks
@tvacherat
Copy link

+1

4 similar comments
@andreaziz
Copy link

+1

@smentek
Copy link

smentek commented Oct 12, 2022

+1

@alibeknow
Copy link

+1

@mehamednews
Copy link

+1

@dabroek
Copy link
Owner

dabroek commented Oct 15, 2022

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.

@DmytroHaponovMD
Copy link

Is it work now for Nest.js ?
image

@dabroek
Copy link
Owner

dabroek commented Oct 17, 2022

@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.

@NarHakobyan
Copy link

@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.

this can't work becouse store field is required for option passed in redisStore function

@smentek
Copy link

smentek commented Oct 20, 2022

@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.

this can't work becouse store field is required for option passed in redisStore function

Is it not why // @ts-ignore is there?

@NarHakobyan
Copy link

@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.

this can't work becouse store field is required for option passed in redisStore function

Is 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.

@FoxxMD
Copy link

FoxxMD commented Oct 20, 2022

@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

@smentek
Copy link

smentek commented Oct 20, 2022

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",

@assisgui
Copy link

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",

@cskiwi
Copy link

cskiwi commented Oct 21, 2022

@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],
}),

@SerhiiBabich
Copy link

Any update on when will this be completed?

@mihailgolban
Copy link

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",

@SerhiiBabich
Copy link

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?

@NarHakobyan
Copy link

NarHakobyan commented Oct 27, 2022

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 :)

@conioX
Copy link

conioX commented Nov 3, 2022

Hi @dabroek, any news for the Type, my repo not allow ts ignore lol

@puzzle9
Copy link

puzzle9 commented Jan 26, 2023

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() from config, 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 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.
  • 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

@ajfranzoia
Copy link

For me it worked with cache-manager-redis-yet using this config:

useFactory: async () => {
  return {
    store: await redisStore({
      // client options
    }),
  };
}

@anilahir
Copy link

anilahir commented Apr 3, 2023

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,
})

@Justin3go
Copy link

Justin3go commented May 14, 2023

我想要在docker中使用,但会一直显示redis的自定义配置无效的问题,就像下面这样,无论port还是host都仍然使用的默认的:

image

我是这样解决的,在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')}`,
        }),
      }),
    }),

@Akupsmee
Copy link

Akupsmee commented Jun 2, 2023

this works for me with the latest package versions:

CacheModule.register({
      store: async () =>
        await redisStore({
          socket: {
            host: 'localhost',
            port: 6379,
          },
          ttl: 10000,
        }),
      isGlobal: true,
    })

@igmrrf
Copy link

igmrrf commented Jun 3, 2023

@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",

@jlopez994
Copy link

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",

@SirPhemmiey
Copy link

SirPhemmiey commented Jul 1, 2023

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

@mengtongun
Copy link

mengtongun commented Jul 14, 2023

This is my solution, works with latest version implement same as @jlopez994 :

import { RedisClientOptions } from 'redis';
import { redisStore } from 'cache-manager-redis-yet';
import { ConfigModule, ConfigService } from '@nestjs/config';
CacheModule.registerAsync<RedisClientOptions>({
 imports: [ConfigModule],
 useFactory: async (cfg: ConfigService) => ({
   store: await redisStore({
    socket: {
      host: cfg.get('REDIS_HOST'),
      port: parseInt(cfg.get('REDIS_PORT ') || '6379'),
    },
    password: cfg.get('REDIS_PASSWORD'),
    ttl: cfg.get('REDIS_TTL'),
  }),
 }),
 inject: [ConfigService]
}),
"@nestjs/common": "^10.0.5",
"cache-manager": "^5.2.3",
"cache-manager-redis-yet": "^4.1.2",
"redis": "^4.6.7",

This worked for me.

  • CacheTTL() worked fine.

  • Cache Manager
    set: (key: string, value: unknown, ttl?: number) also worked fine.

@elouizbadr
Copy link

This is my solution, works with latest version implement same as @jlopez994 :

import { RedisClientOptions } from 'redis';
import { redisStore } from 'cache-manager-redis-yet';
import { ConfigModule, ConfigService } from '@nestjs/config';
CacheModule.registerAsync<RedisClientOptions>({
 imports: [ConfigModule],
 useFactory: async (cfg: ConfigService) => ({
   store: await redisStore({
    socket: {
      host: cfg.get('REDIS_HOST'),
      port: parseInt(cgf.get('REDIS_PORT ') || '6379'),
    },
    password: cfg.get('REDIS_PASSWORD'),
    ttl: cfg.get('REDIS_TTL'),
  }),
 }),
 inject: [ConfigService]
}),
"@nestjs/common": "^10.0.5",
"cache-manager": "^5.2.3",
"cache-manager-redis-yet": "^4.1.2",
"redis": "^4.6.7",

This worked for me.

  • CacheTTL() worked fine.
  • Cache Manager
    set: (key: string, value: unknown, ttl?: number) also worked fine.

Thank you @mengtongun for this solution. Just a side note, you've got a typo in the following line (Where cgf should be cfg):

port: parseInt(cgf.get('REDIS_PORT ') || '6379'),

@SlinkyPotato
Copy link

SlinkyPotato commented Aug 5, 2023

This is interesting.

A few things:

The last commit from this project was October 16 2022.

This project is forked to https://github.com/node-cache-manager/node-cache-manager-redis-yet#license

It is officially maintained by node-cache-manager according to NestJS docs https://docs.nestjs.com/techniques/caching#different-stores
https://github.com/node-cache-manager/node-cache-manager#store-engines

Is this project abandoned?

Here is a working example from node-cache-manager-redis-yet

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

@Module({
  imports: [
    CacheModule.register<RedisClientOptions>({
      store: redisStore,
      socket: {
        host: process.env.REDIS_HOST ?? 'localhost',
        port: parseInt(process.env.REDIS_PORT ?? '6379'),
      },
    }),
  ],
})
export class TestModule {}
...
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
...
await this.cacheManager.set('test', 'test-value');
const testVal = await this.cacheManager.get('test');
...
"@nestjs/common": "^10.0.5",
"cache-manager": "^5.2.3",
"cache-manager-redis-yet": "^4.1.2",
"redis": "^4.6.7",

@Biigode
Copy link

Biigode commented Aug 7, 2023

This is interesting.

A few things:

The last commit from this project was October 16 2022.

This project is forked to https://github.com/node-cache-manager/node-cache-manager-redis-yet#license

It is officially maintained by node-cache-manager according to NestJS docs https://docs.nestjs.com/techniques/caching#different-stores

Is this project abandoned?

Here is a working example from node-cache-manager-redis-yet

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

@Module({
  imports: [
    CacheModule.register<RedisClientOptions>({
      store: redisStore,
      socket: {
        host: process.env.REDIS_HOST ?? 'localhost',
        port: parseInt(process.env.REDIS_PORT ?? '6379'),
      },
    }),
  ],
})
export class TestModule {}
...
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
...
await this.cacheManager.set('test', 'test-value');
const testVal = await this.cacheManager.get('test');
...
"@nestjs/common": "^10.0.5",
"cache-manager": "^5.2.3",
"cache-manager-redis-yet": "^4.1.2",
"redis": "^4.6.7",

This solutions works for me thanks.
Follow the images

image

image

image

@zenstok
Copy link

zenstok commented Aug 22, 2023

Please be cautious regarding this issue that I came across while using cache-manager-redis-yet. This issue could potentially lead to a security vulnerability within your application, especially if you are depending on the @Exclude() class validator decorator to conceal attributes from the frontend.

@NinjaMax
Copy link

Maybe I can help someone.
In my case :

  • CacheTTL() doesn't worked.
  • Cache Manager
    set: (key: string, value: unknown, ttl?: number) also doesn't worked.
  • return { store: redisStore as unknown as CacheStore, ttl: 5000}; doesn't worked.

With TTL - this is workes for me.

import { CacheStore, Module } from '@nestjs/common';
import { RedisClientOptions, createClient } from 'redis';
import { CacheModule } from '@nestjs/cache-manager';
//--------------------------------------------------------
CacheModule.registerAsync<RedisClientOptions>({
      imports: [ConfigModule.register({ folder: './config' })],
      useFactory: async (configService: ConfigService) => {
        const store = createClient({
          socket: {
            host: configService.get('REDIS_HOST'),
            port: +configService.get('REDIS_PORT'), 
          },
        });
        await store.connect().catch(console.error);
        const redisStore = new RedisStore({
          client: store,
          prefix: 'tyre-no-offset: ', 
          ttl: 5000,
        });
        return { store: redisStore as unknown as CacheStore };
      },
      isGlobal: true,
      inject: [ConfigService],
    }),
//--------------------------------------------

controller:

 @UseInterceptors(CacheInterceptor)
 @CacheKey('no-offset')
 @Get('/no-offset')
 findTyresWithoutLimit(@Query('width') width: string,) {
   return this.tyresService.findAllTyresWithoutOffset(width);
 }

@mohit4bug
Copy link

Seems to work!

import { AppController } from "@/app.controller"
import { AppService } from "@/app.service"
import { CacheModule } from "@nestjs/cache-manager"
import { Module } from "@nestjs/common"
import { ConfigModule, ConfigService } from "@nestjs/config"
import { redisStore } from "cache-manager-redis-yet"
import type { RedisClientOptions } from "redis"

@Module({
  imports: [
    CacheModule.registerAsync<RedisClientOptions>({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        store: await redisStore({
          ttl: parseInt(configService.get<string>("REDIS_TTL")),
          socket: {
            host: configService.get<string>("REDIS_HOST"),
            port: parseInt(configService.get<string>("REDIS_PORT")),
          },
        }),
      }),
      isGlobal: true,
    }),
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

@ygweric
Copy link

ygweric commented Apr 29, 2024

  • set: (key: string, value: unknown, ttl?: number) also doesn't worked.

same bug with me

@kokole12
Copy link

kokole12 commented May 27, 2024

This worked for me so far
`/* eslint-disable @typescript-eslint/ban-ts-comment */
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { CacheInterceptor, CacheModule } from '@nestjs/cache-manager';
import { RedisClientOptions } from 'redis';
import { redisStore } from 'cache-manager-redis-store';

@module({
imports: [
CacheModule.register({
// @ts-ignore
store: async () =>
await redisStore({
socket: {
host: 'localhost',
port: 6379,
},
}),
}),
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}

@pedroaraujo1952
Copy link

Any update on when will this be completed?

@toknT
Copy link

toknT commented Jul 10, 2024

Hi it's 2024, and I am using redis v5

for redis v5 , use cache-manager-redis-yet

#40 (comment)

@samuelgoldenbaum
Copy link

Using the following does not close the redis connection when app.close() is called and will also leave your tests hanging.

CacheModule.registerAsync<RedisClientOptions>({
      useFactory: async (configService: AppConfigService) => ({
        store: await redisStore({
          ttl: configService.cache.ttl,
          socket: {
            host: configService.cache.host,
            port: configService.cache.port
          }
        })
      }),
      inject: [AppConfigService],
      isGlobal: true
    }),

I had to implement the following to manually close the client:

export class AppModule implements OnModuleDestroy {
     constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

     async onModuleDestroy() {
       // @ts-expect-error as store.client is not currently exposed
       await this.cacheManager.store.client.quit()
     }
}

@MaazEllahiKhan
Copy link

MaazEllahiKhan commented Jul 31, 2024

update: double check the port you are running redis server on, I changed mine to 10001 and was trying to access it on 6379 (I was getting no error). Don't be like me. The configurations were working fine both redis-yet and redis-store 2.0.0.

Seems to work!

import { AppController } from "@/app.controller"
import { AppService } from "@/app.service"
import { CacheModule } from "@nestjs/cache-manager"
import { Module } from "@nestjs/common"
import { ConfigModule, ConfigService } from "@nestjs/config"
import { redisStore } from "cache-manager-redis-yet"
import type { RedisClientOptions } from "redis"

@Module({
  imports: [
    CacheModule.registerAsync<RedisClientOptions>({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        store: await redisStore({
          ttl: parseInt(configService.get<string>("REDIS_TTL")),
          socket: {
            host: configService.get<string>("REDIS_HOST"),
            port: parseInt(configService.get<string>("REDIS_PORT")),
          },
        }),
      }),
      isGlobal: true,
    }),
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

can u please share the packages with versions you are using? redis, cache-manager, redis-yet or redis-store? any other related?
I have tried multiple configurations with different versions,
cache-manager-ioredis-yet,
cache-manager-redis-yet,
cache-manager-redis-store
with rediisIO, redis and multiple cache-manager packages from 3.0 to 5.0 but still unable to get data on store.
I am getting undefined from set and get right now using your configurations.
I was able to get ok from set but didn't find data on redis visualizer with cache-manager-redis-store pakage 2.0.0.
Really stuck in this any help is welcome.
My packages:
cache-manager": "^5.2.3",
"cache-manager-redis-yet": "^4.1.2",
"redis": "^4.6.7",

@minikdev
Copy link

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.

const ttl = (options?.ttl || options?.ttl === 0) ? options.ttl : config.ttl;

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",

thanks bro you saved me

@ktphuc1994
Copy link

@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 one is working for me. Current version:

 "@nestjs/cache-manager": "^2.2.2",
 "cache-manager": "^5.7.6",
 "redis": "^4.7.0",
 "cache-manager-redis-store": "^3.0.1",

@b310L
Copy link

b310L commented Dec 11, 2024

Hello,
How to use multiple redis CacheModule?
I want to use 2 redis cache with diffrent host.
When i use name, dependency not resolved.

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