nestjs / cache-manager

Cache manager module for Nest framework (node.js) 🗃
MIT License
117 stars 22 forks source link

TypeError: ttl must be a positive integer if specified #324

Closed matiasgarcia closed 5 months ago

matiasgarcia commented 5 months ago

Is there an existing issue for this?

Current behavior

I have the following code that configures CacheModule with an in-memory or redis store depending on the environment variable configuration.

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 * as path from 'path';
import { ConfigSchema } from './config.schema';
import { validator } from './validator';

@Module({
  imports: [
    CacheModule.registerAsync({
      imports: [
        ConfigModule.forRoot({
          envFilePath: path.resolve(
            process.cwd(),
            `.env.${process.env.NODE_ENV}`,
          ),
          validate: validator(ConfigSchema, (env: Record<string, unknown>) => ({
            driver: env.CACHE_DRIVER,
            url: env.CACHE_REDIS_URL,
          })),
        }),
      ],
      useFactory: async (config: ConfigService<ConfigSchema>) => {
        const driver = config.getOrThrow('driver', { infer: true });
        if (driver === 'in-memory') return {};

        if (driver === 'redis') {
          return await redisStore({
            url: config.getOrThrow('url', { infer: true }),
          });
        }

        throw new Error(`incompatible option for driver: ${driver}`);
      },
      inject: [ConfigService],
    }),
  ],
  exports: [CacheModule],
})
export class CacheInfrastructureModule {}

When driver is redis, I get the following stack trace:

[Nest] 12331  - 27/02/2024, 19:18:57   ERROR [ExceptionHandler] ttl must be a positive integer if specified
TypeError: ttl must be a positive integer if specified
    at new LRUCache (/Users/matias/projects/services-nuvem-pago-commons/node_modules/cache-manager/node_modules/lru-cache/src/index.ts:1130:15)
    at memoryStore (/Users/matias/projects/services-nuvem-pago-commons/node_modules/cache-manager/dist/stores/memory.js:27:22)
    at Object.caching (/Users/matias/projects/services-nuvem-pago-commons/node_modules/cache-manager/dist/caching.js:11:48)
    at cachingFactory (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/cache-manager/dist/cache.providers.js:41:37)
    at InstanceWrapper.useFactory [as metatype] (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/cache-manager/dist/cache.providers.js:48:19)
    at Injector.instantiateClass (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/core/injector/injector.js:354:55)
    at callback (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/core/injector/injector.js:56:45)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Injector.resolveConstructorParams (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/core/injector/injector.js:136:24)
    at Injector.loadInstance (/Users/matias/projects/services-nuvem-pago-commons/node_modules/@nestjs/core/injector/injector.js:61:13)

Simplifying the useFactory function to always create redis, I get this error:

      useFactory: async (config: ConfigService<ConfigSchema>) => {
        return await redisStore({
          url: config.getOrThrow('url', { infer: true }),
        });
      },
src/shared/infrastructure/cache/cache.module.ts:24:7 - error TS2322: Type '(config: ConfigService<ConfigSchema>) => Promise<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/g...' is not assignable to type '(...args: any[]) => CacheModuleOptions<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/...'.
  Type 'Promise<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); ... 15 m...' is not assignable to type 'CacheModuleOptions<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"...'.
    Type 'Promise<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); ... 15 m...' is not assignable to type 'Promise<CacheModuleOptions<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CON...'.
      Type 'RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); ... 15 more ...;...' is not assignable to type 'CacheModuleOptions<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"...'.
        Type 'RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); ... 15 more ...;...' is not assignable to type 'CacheManagerOptions'.
          Types of property 'ttl' are incompatible.
            Type '(key: string) => Promise<number>' is not assignable to type 'number'.

24       useFactory: async (config: ConfigService<ConfigSchema>) => {
         ~~~~~~~~~~

  node_modules/@nestjs/cache-manager/dist/interfaces/cache-module.interface.d.ts:42:5
    42     useFactory?: (...args: any[]) => Promise<CacheModuleOptions<StoreConfig>> | CacheModuleOptions<StoreConfig>;
           ~~~~~~~~~~
    The expected type comes from property 'useFactory' which is declared here on type 'CacheModuleAsyncOptions<RedisStore<RedisClientType<{ graph: { CONFIG_GET: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG_GET"); configGet: typeof import("/Users/matias/projects/services-nuvem-pago-commons/node_modules/@redis/graph/dist/commands/CONFIG...'

Libs:

Minimum reproduction code

https://github.com/matiasgarcia/nestjs-advanced-architecture

Steps to reproduce

No response

Expected behavior

Should work

Package version

2.2.1

NestJS version

9.4.1

Node.js version

20.9.0

In which operating systems have you tested?

Other

No response

kamilmysliwiec commented 5 months ago

Thank you for taking the time to submit your report! From the looks of it, this could be better discussed on our Discord. If you haven't already, please join here and send a new post in the #⁠ 🐈 nestjs-help forum. Make sure to include a link to this issue, so you don't need to write it all again. We have a large community of helpful members, who will assist you in getting this to work.