Git Product home page Git Product logo

type-cacheable's People

Contributors

caolvchong avatar cernytomas avatar dependabot-preview[bot] avatar dependabot[bot] avatar dmeents avatar dvarnai avatar evilworm avatar foxling avatar herebebogans avatar johanwillfred avatar joshuaslate avatar julianpoy avatar klebeer avatar lbayas avatar lucasrcosta avatar olehcambel avatar oschlegel avatar seawatts avatar sergeymell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

type-cacheable's Issues

[BUG] CacheClear not working on Azure Redis

Describe the bug
type-cacheable CacheClear failure on method updateUserDetails due to client error: Cannot read property 'redis_version' of undefined when using @CacheClear

To Reproduce
Steps to reproduce the behavior:
When using the packages :

  • "@type-cacheable/core": "^9.1.0"
  • "@type-cacheable/redis-adapter": "^9.1.0 ,
  • "ioredis": "^4.19.4"
  • "redis": "^3.0.2",

and connecting to Azure Redis Cache, the following error appears (when debugging is enabled):

type-cacheable CacheClear failure on method ...... due to client error: Cannot read property 'redis_version' of undefined and the clearing the key is not working

Expected behavior
The cachekey should be cleared

Additional context
Analysis learns that this line of code in the index.js of the adapter introduces the exception

                    if (compareVersions(this.redisClient.**server_info**.redis_version, REDIS_VERSION_UNLINK_INTRODUCED) >= 0) {
                        this.redisClient.unlink(keyOrKeys, RedisAdapter.responseCallback(resolve, reject));
                    }

Debugger learns that in 'our' situation the property is not server_info but serverInfo , when replacing this property, everything works as expected again

Redis adaptor ignores cacheKey and just sets the key to the hashKey

When using NodeCache, the generated key in the NodeCache is hashKey:cacheKey, as expected. When using Redis, the generated key is just hashKey. Looking at the RedisAdaptor, it looks like it deliberately parses out the cacheKey and just sets it as a field instead of using it for the key itself.

What's the reasoning behind this behavior?

Adapter inconsistencies

Redis and IoRedis adapters store values differently, IoRedisAdapter doesn't support hmset like RedisAdapter does. Furthermore, IoRedisAdapter doesn't do any transformation for numbers and strings.

As a better solution, I propose adding a transform function parameter to the cacheable decorator, that would by default transform objects, numbers, booleans. This would also make it possible to parse custom types automatically, making the rest of the application completely unaware whether the value was returned from cache or not.

Thoughts? If you reckon it's a good idea I'll submit a PR

Configureable caching strategy

Do you thought about supporting different caching strategies? Currently your caching mechanism returns always the cached value if some exists, which is a kind of "Cache First" strategy. I thought of a "Cache as Fallback" strategy where the original method is always executed. In case the method returns a result within a certain timespan the result is returned and the Cache is updated. If the method doesn't Return a result in time the cached value is used and the Cache is updated when the method finally completes.

The caching strategy could bei passed as option to the cachable decorator like so:

@Cacheable({ strategy: new CacheAsFallbackStrategy(3000) })

The library could also expose a caching strategy interface, this way consumers could write their own caching strategies. Please Tell me what you think about this idea.

Usage of @types in dependencies

Actually, do we need types like @types/redis, @types/ioredis, @types/node-cache in dependencies of package.json? I mean, when users install your lib they also install appropriate lib for caching with its own types.

I can make PR later.

Fallback to in-memory cache

In some cases it would be nice if a in-memory cache would be used by Cachable and CacheClear decorators if no other cache is defined. This would open the possibility to have a fallback for caching if a connection to the actual cache could not be established. This behavior should be optional, for example by a fallbackToInMemoryCache flag in the CacheManager options.

Why do you think of this idea?

[Bug/Question] setClient throws error when setting it null & options.ttlSeconds not set

Hello !

Not sure if it's a bug or if we don't use this package correctly
We're using this package (10.1.0) with @redis/client

When our redis loose it's connection, we want to disable the cache, until redis reconnect.
To do so, we call the CacheManager with .setClient(null)

As client is null, and we don't specify the ttlSeconds, this.client.getClientTTL() throws an error

setClient(client) {
    this.client = client;
    if (this.options && !this.options.ttlSeconds) {
        this.options.ttlSeconds = this.client.getClientTTL();
    }
}

Are we missing something ? is there an other way to disable the cache temporarily ?

As a workaround, we just catch the call to setClient(null), and do nothing with this

I can propose a PR and add an condition on this.client in the if.

from:

if (this.options && !this.options.ttlSeconds) {

to:

if (this.client && this.options && !this.options.ttlSeconds) {

Silently ignore if connection is not available

I am using ioredis with type-cacheable on AWS lambdas, and from time to time, the connection to Redis will time out.

Some of my APIs are time-sensitive, and if the connection to Redis fails - I wanna skip the cache and proceed to DynamoDB as soon as possible.

Here's how Redis client configuration:

const REDIS_CONNECTION_RETRY_COUNT: number = 1;
const redisOptions: RedisOptions = {
  host: config.redis.host || 'localhost',
  port: config.redis.port || 6379,
  retryStrategy: (times): number | undefined => {
    // reconnect after
    if (times > REDIS_CONNECTION_RETRY_COUNT) {
      return undefined;
    }
    return 50;
  },
  showFriendlyErrorStack: true,
  keepAlive: 10000,
  connectTimeout: 1500,
  maxRetriesPerRequest: REDIS_CONNECTION_RETRY_COUNT,
  noDelay: true,
  lazyConnect: false,
};

As you can see, I give 1.5 seconds for connection and retry once, and if that fails - I wanna move on.

I also don't want my logs to indicate errors, so I simply log them as info

redisClient.on('error', (err) => {
  if (err?.code === 'ETIMEDOUT') {
    logger.info('Redis connection timed out, retrying...');
  } else {
    logger.error(err);
  }
  // redisClient.disconnect(false);
});

Which all works great, except, inside ioredis-adapter, if the connection is not open by the time it tries to perform get - it will throw an error

(node:2991) UnhandledPromiseRejectionWarning: Error: Connection is closed.
    at IoRedisAdapter.<anonymous> (/Users/user/Dev/projects/events-streaming/node_modules/@type-cacheable/ioredis-adapter/dist/index.js:42:51)
    at Generator.next (<anonymous>)
    at /Users/user/Dev/projects/events-streaming/node_modules/@type-cacheable/ioredis-adapter/dist/index.js:8:71

Is there a way to catch this error or tell the adapter to skip if the connection is not there?

Thank you

Cacheable decorator breaks other decorators applied to the method

Describe the bug
If apply @Cacheable decorator together with some other decorators it will eliminate all the decorators which come after it.

To Reproduce
If to use it within the NestJS Controller like this

    @Cacheable({
        cacheKey: 'my-cache-key',
        ttlSeconds: 1000
    })
    @Get('chart')
    async getMarketChart(
        @Query() query: MarketChartQuery,
    ) {
        ...
    }
    ```
This endpoint will not handle get requests. In addition, no swagger documentation that may be contained within `MarketChartQuery` DTO will be available.

**Expected behavior**
Each applied to the method should work independently

node-cache error

Since moving to latest version

- "type-cacheable": "^2.2.1",
+ "type-cacheable": "^4.1.2",

I'm getting error on ts build *. I use ioredis for caching. Should I install node-cache as devDependencies to fix it?
*

node_modules/type-cacheable/dist/adapters/NodeCacheAdapter.d.ts:1:28 - error TS2307: Cannot find module 'node-cache'.

1 import * as NodeCache from 'node-cache';
                             ~~~~~~~~~~~~

node_modules/type-cacheable/dist/util/useAdapter.d.ts:2:28 - error TS2307: Cannot find module 'node-cache'.

2 import * as NodeCache from 'node-cache';
     

[BUG] Which package manager should be used for setting up this project?

I'm attempting to clone and install the repository, to investigate a bug and hopefully contribute back. I can see an .nvmrc (Node 10.7.0) and a Lerna setup. However, there are both package-lock.json and yarn.lock lockfiles.

Attempting to setup the project with yarn (1.22.5) throws the following error:

$ yarn

yarn install v1.22.5
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/4] Resolving packages...
[2/4] Fetching packages...
error [email protected]: The engine "node" is incompatible with this module. Expected version ">= 10.14.2". Got "10.7.0"
error Found incompatible module.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

With npm (6.1.0 from the nvm setup), I'm able to install the dependencies, but neither npm run build nor npm run test complete without errors.

Which package manager should be used to install this project's dependencies?

Noop is not working when client is defined

Hi,
Setting the noop to true does not have any effect.
Looking at Cacheable.ts, it looks like the noop check happens only if the client is not defined (which usually will not be the case).

It would seem that it should be outside the if (!client) block...

[BUG] IoRedis adapter returns string values instead of Date

Describe the bug
Using IoRedis adapter, cache saves Date instance value as a string. Getting cached value returns string instead of Date instance.

To Reproduce
Steps to reproduce the behavior:

@Cacheable({ cacheKey: (args) => args[0], hashKey: 'getDateObject', ttlSeconds: 60 * 60 })
public getDate(anyKey: string): { myDate: Date } {
  return { myDate: new Date() }
}
  
public getCachedDate(): void {
  // setting cache first. Returns { myDate: Date }
  const response = this.getDate('some-key')

  // getting data from cache. Returns { myDate: string }
  const wrongResponse = this.getDate('some-key')
}

Expected behavior
Response should be consistent, doesn't matter if loaded from cache or not. Should return date if possible.

Environment:

  • OS: Windows 11 Pro
  • Version: 13.1.0
  • Adapter IoRedis: 14.1.0

Additional context
It's the same problem as this issue #638, except that in this case it is on the IoRedis adapter.

Handle unavailable redis

Hi

I got this package up and running, but when the redis server is unavailable, it always returns an error because it can't connect.
I don't want my application to fail because redis is down, i want it to always execute the method when the redis server is down, is it possible to do this easily ?

Add possibility to clear multiple cacheKey's or auto update cache.

I started developing a simple CRUD api of TODO's and using type-cacheable.

The first problem encountered is "I cannot clear multiple cacheKey's". Why I want this? Because I cache a list of items using a specific cacheKey instead of id.

The second problem encountered is "I want to clear and update immediately", also for multiple cacheKey's. Why I want this? Because I want to clear the cache after updating and automatically re-cache after response.

I can open a PR to develop both of decorators. Is it possible?

Thanks

Extend @Cacheable decorator

Hi @joshuaslate

Trying to extend your @Cacheable decorator to inject some custom metadata:

export function customCacheable(options: CacheOptions): Function {
  // Factory returns the actual decoration function.
  return function (target: Function, propertyKey: string, descriptor: PropertyDescriptor) {

    Reflect.defineMetadata(some custom metadata);
    
    Cacheable(options)(target, propertyKey, descriptor);
  };
}

But whenever I apply this to my function, it always misses the cache, any obvious suggestions?
Thank you

redis-adapter@10 specifies peer core@9

"@type-cacheable/core": "^9.1.0",

Results in a peer dependency error when installing.

% npm install -S @type-cacheable/redis-adapter@10                                                     (main +x!>)
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: @kw/[email protected]
npm ERR! Found: @type-cacheable/[email protected]
npm ERR! node_modules/@type-cacheable/core
npm ERR!   @type-cacheable/core@"^10.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @type-cacheable/core@"^9.1.0" from @type-cacheable/[email protected]
npm ERR! node_modules/@type-cacheable/redis-adapter
npm ERR!   @type-cacheable/redis-adapter@"10" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Clear all cacheKeys by hashKey

Hello. First of thanks for this awesome lib :) I wanted to ask if it is somehow possible to clear all cacheKeys with the same hashKey?

I tried to use CacheClear like this:

@CacheClear({
    hashKey: (args) => `projectPermissions-${args[0]}`,
})
async clearProjectCache(projectId: string) {
  console.log('clearing cache for project', projectId);
}

but it does not clear and I need to also define a cache key like this:

@CacheClear({
    cacheKey: (args) => args[0],
    hashKey: (args) => `projectPermissions-${args[1]}`,
 })
 async clearProjectCache(userId: string, projectId: string) {
   console.log('clearing cache for project-user', projectId);
 }

Thank you!

WRONGTYPE on hgetall for RedisAdapter

example

class TestClass {
    @Cacheable({ hashKey: 'user' })
    async get(id: string): Promise<string> {
        console.log('call:get')

        return id;
    }
}

const testClass = new TestClass();

// ...
// cached
const t = await testClass.get('1')
// unable to get from cache, so running func
const t2 = await testClass.get('1')

so it will store:

key: user:c582768569539b3bc297a72bbc38ae87
value: 1

Error occurs when it tries to use hgetall (by detecting cacheKey.includes(':'). However, it should use get operator in this case

[Feature Request] IoRedis Adapter Scan Keys on Redis Cluster

Is your feature request related to a problem? Please describe.
Currently, the IoRedisAdapter keys method uses the ioRedis scan command to search for a pattern
The problem is that the scan command only works on no-cluster environments, and when we use the key command, there are not the right responses to the matches.

 public async keys(pattern: string): Promise<string[]> {
    let keys: string[] = [];
    let cursor: number | null = 0;

    while (cursor !== null) {
      const result = (await this.redisClient.scan(cursor, 'MATCH', pattern, 'COUNT', 1000)) as
        | [string, string[]]
        | undefined;

      if (result) {
        // array exists at index 1 from SCAN command, cursor is at 0
        keys = [...keys, ...result[1]];
        cursor = Number(result[0]) !== 0 ? Number(result[0]) : null;
      } else {
        cursor = null;
      }
    }

    return keys;
  }

Describe the solution you'd like
To support search in a Redis cluster is needed to list all the master nodes of the cluster and scan in all of those nodes.

  public async keys(pattern: string): Promise<string[]> {
    if(this.redisClient instanceof Cluster) {
      const cluster = this.redisClient as Cluster;
      const keys = cluster.nodes('master').map((node) => this.scanKeys(node, pattern));
      return (await Promise.all(keys)).flat();
    }
    return  this.scanKeys(this.redisClient, pattern);
  }

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

[BUG] mis match in peerDepandancy of @type-cacheable/lru-cache-adapter

Describe the bug
The version of @type-cacheable/core in the devDependancy and peerDependancy are different

  "devDependencies": {
    "@type-cacheable/core": "^12.0.0",
  },
  "peerDependencies": {
    "@type-cacheable/core": "^11.0.0",
  },

https://github.com/joshuaslate/type-cacheable/blob/main/packages/lru-cache-adapter/package.json#L41

this causing installing the lru-cache adapter fails in node 18

npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: @type-cacheable/[email protected]
npm ERR! Found: @type-cacheable/[email protected]
npm ERR! node_modules/@type-cacheable/core
npm ERR!   @type-cacheable/core@"^12.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @type-cacheable/core@"^11.0.0" from @type-cacheable/[email protected]
npm ERR! node_modules/@type-cacheable/lru-cache-adapter
npm ERR!   @type-cacheable/lru-cache-adapter@"^14.0.0" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: @type-cacheable/[email protected]
npm ERR! node_modules/@type-cacheable/core
npm ERR!   peer @type-cacheable/core@"^11.0.0" from @type-cacheable/[email protected]
npm ERR!   node_modules/@type-cacheable/lru-cache-adapter
npm ERR!     @type-cacheable/lru-cache-adapter@"^14.0.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Incorrect usage of "scan" while deleting pattern matched cache entries

Currently we have single command being executed while deleting cached entries:

public async keys(pattern: string): Promise<string[]> {
  const result = await this.redisClient.scan('0', 'MATCH', `*${pattern}*`, 'COUNT', 1000);

  return result ? result[1] : [];
}

This is wrong. Redis SCAN command is cursor based and you need to check the response if the cursor position is "0". If it's not "0" then you need to continue executing the scan command in a loop.

I checked only the ioredis implementation, but it's probably true for other adapters as well. It should look something like this:

public async keys(pattern: string): Promise<string[]> {
  let keys:Array<string> = [];
  let cursor = 0;
  do {
    const result = await this.redisClient.scan(cursor, 'MATCH', `*${pattern}*`, 'COUNT', 1000);
    if(result) {
      cursor = Number(result[0]);
      keys = keys.concat(result[1]);
    } else {
      cursor = 0;
    }
  } while(cursor);

  return keys;
}

Also I would suggest dropping the hardcoded wildcards and let user decide where to put them. Most of the time you will have a constant prefix and wildcard only at the end. However this might be a breaking change to already implemented code...

CacheUpdate is not working properly

Hi again @joshuaslate :)

I was trying to use @CacheUpdate decorator from version 6.2.0 but for some behaviours I couldnt.

When I use @CacheUpdate on update operation, normally I have the my entity and possibility to set cacheKey by id, example:

  @CacheUpdate({
    cacheKey: ([{ id }]: any[]) => id,
    cacheKeysToClear: 'todos',
  })
  async updateTodo(todo: Todo, dataToUpdate: TodoUpdateInput): Promise<Todo> {
    const todoToUpdate = Object.assign(todo, dataToUpdate);
    const updatedTodo = await this.todoRepository.save(todoToUpdate);

    return updatedTodo;
  }

Everything here works like a charm. But in my create operation I dont have id available immediatelly, example:

  @CacheUpdate({
    cacheKey: (data: any[]) => {
       return 'invalid-id';
     },
     cacheKeysToClear: 'todos',
  })
  async createTodo(task: string): Promise<Todo> {
    const todoAsEntity = await this.todoRepository.create({ task });
    const todo = await this.todoRepository.save(todoAsEntity);

    return todo;
  }

When I try to create cacheKey data contains the task name instead of the result.

Any suggestions to fix it?

[question] How to clear keys by pattern

Hi, i have a question regarding cache keys, maybe you can help me. I have cache keys which look like this: items_[country]_[language]_[userId], where country, language and userId are dynamic values. When a item is created, updated, or deleted i want to clear all cache keys that start with items_. Is it possible to clear cache keys by a regex pattern or something similar?

[Question]: how i can disable the whole caching mechanism with a flag

Congratulations for the good work!

Is your feature request related to a problem? Please describe.
We want to use just one flag to disable the cache (from the cache manager maybe) for the whole application. This is useful when you want for example to disable the cache from an env setting due to a bug or something. Can you please let me know how can i achieve it?

Describe the solution you'd like
I want to pass an variable to cache manager to stop caching for the whole application

Describe alternatives you've considered
I have tried not setting the cache manager but this doesn't work:

const cacheIsDisabled = true;
if (cacheIsDisabled) return;

cacheManager.setOptions(<CacheManagerOptions>{
      excludeContext: true
      ttlSeconds: 1000
})
cacheManager.client = nodeCacheAdapter

Additional context
No

Thanks in advanced!

[BUG] Decorator doesn't function as a lock

Describe the bug
When calling the decorated function multiple times before the promise is resolved, it will actually call it multiple times, meaning if I want to cache a request to the DB, if I have 100 calls to that function, 70 of them might trigger a call to the DB before it's actually saved and only the last 30 will be cached.
This basically makes it useless :(

To Reproduce
Steps to reproduce the behavior:

  1. Create an async function that takes a second.
  2. Call it multiple times
  3. See that the inner function is actually triggered...

Expected behavior
The function is locked until a response is returned and then it's cached.

[BUG]: Getting error while running it

Module not found: Error: Can't resolve 'crypto' in '/Users/patrick/git/patrick/github-activity/node_modules/@type-cacheable/core/dist/util'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }

lru-cache typings

Sorry - I didn't appreciate in my recent commits

950c13d

that the now stub @types/lru-cache package differs from lru-cache official typings.

See version 8 note.

https://github.com/isaacs/node-lru-cache/blob/main/CHANGELOG.md

Rewritten in TypeScript, so pretty much all the types moved around a lot.

The useAdapter LRUCache type

LRUCache<string, T, unknown>

now doesn't match lru-cache's

LRUCache<K extends {}, V extends {}, FC = unknown>

Could have a look at? I'm not familiar enough with generics.

At the moment you would need to use a workaround like this for the README.md example to work

useAdapter(client as unknown as LRUCache<string, {}, unknown>);

Individual expire not working

Hello.

I'm trying to set a individual cache time to live but I'm not getting the expected result. I'm using NodeCache as cache platform. Here's my sample code:

const client = new NodeCache({ stdTTL: 120, checkperiod: 120 * 0.2 })
useNodeCacheAdapter(client)
@Cacheable({ ttlSeconds: 5 })
public async getAll(venueIds?: Array<string>) {
        return this.getAllByFilter(venueIds, sitesByVenue)
}

I tried setting hashKey and cacheKey, but no success. I also tried to create a custom CacheClient(wrap of a NodeCache) but not worked either.

I don't know if I doing something wrong or what.

Conditionally skip caching for values

Is your feature request related to a problem? Please describe.
Sometimes you don't want to cache certain values. For Example: When you integrate a api which is badly coded and returns status 200 but with a error in the body, this would probably be a value you don't want to cache.

Describe the solution you'd like
A isCacheable option for the Cachable decorator which takes a function with the value to be cached as parameter and expects a boolean, wether or not this value should be cached.

Describe alternatives you've considered
The application integrating the api has to implement custom logic (for example throwing a error) to prevent the value from being cached.

Incorrect peer dependency in redis adapter package

Describe the bug
The @type-cacheable/redis-adapter package version 14.0.0 has a peer dependency to @type-cacheable/core of version 10.0.0 and a dev dependecy to @type-cacheable/core of version 11.0.0, this looks not correct to me.

Expected behavior
The @type-cacheable/redis-adapter package version 14.0.0 should have a peer dependency to @type-cacheable/core of version 11.0.0.

Missing index.d.ts in latest release

After upgrading to the latest release, I see it's missing a types declaration file. This should be included, right? It was included in the older version I was using, 0.1.9.

Namespace 'NodeCache' has no exported member 'NodeCache'

Hi and thanks for the package!

Description

I've recently run into an issue where running tsc (typescript build command I'm using) is failing and pointing to type-cacheable as the culprit. I'm not sure if this is an issue with the package or not but I'll describe the problem and how I solved it so perhaps a PR can be discussed.

The Error Message

$ tsc
node_modules/type-cacheable/dist/adapters/NodeCacheAdapter.d.ts:6:44 - error TS2694: Namespace 'NodeCache' has no exported member 'NodeCache'.

      constructor(nodeCacheClient: NodeCache.NodeCache);
                                             ~~~~~~~~~

node_modules/type-cacheable/dist/util/useAdapter.d.ts:4:62 - error TS2694: Namespace 'NodeCache' has no exported member 'NodeCache'.

  export declare const useNodeCacheAdapter: (client: NodeCache.NodeCache) => void;
                                                               ~~~~~~~~~


Found 2 errors.

I think it's because the type definitions in dist/util/useAdapter.d.ts and dist/adapters/NodeCacheAdapter.d.ts are incorrect. [email protected] doesn't have the NodeCache.NodeCache property anymore. I was able to fix it by just removing the second NodeCache.

Updated Files

Below are the files I updated in type-cacheable with that usage to get it to work:

dist/util/useAdapter.d.ts

import { RedisClient } from 'redis';
import * as NodeCache from 'node-cache';
export declare const useRedisAdapter: (client: RedisClient) => void;
export declare const useNodeCacheAdapter: (client: NodeCache) => void;

dist/adapters/NodeCacheAdapter.d.ts

import * as NodeCache from 'node-cache';
import { CacheClient } from '../interfaces';
export declare class NodeCacheAdapter implements CacheClient {
    static responseCallback: (resolve: Function, reject: Function) => NodeCache.Callback<any>;
    private nodeCacheClient;
    constructor(nodeCacheClient: NodeCache);
    getClientTTL(): number;
    get(cacheKey: string): Promise<any>;
    /**
     * set - Sets a key equal to a value in a NodeCache cache
     *
     * @param cacheKey The key to store the value under
     * @param value    The value to store
     * @param ttl      Time to Live (how long, in seconds, the value should be cached)
     *
     * @returns {Promise}
     */
    set(cacheKey: string, value: any, ttl?: number): Promise<any>;
    del(cacheKey: string): Promise<any>;
}

Implementation of type-cacheable

import * as NodeCache from "node-cache";

// Other app setup stuff

const cacheClient =  new NodeCache.default();
useNodeCacheAdapter(cacheClient);

Packages Used:

Package Version
type-cacheable 1.2.1
node-cache 5.0.0
@types/node-cache 4.1.3

Thanks again! Let me know if I need to provide more context.

[BUG] set is called on cache client even if an error is thrown

Describe the bug

I'm using a IoRedisAdapter with a custom strategy that inherits from the provided DefaultStrategy.

When my decorated function throws an error, Redis SET operation is still called.

After investigating a bit, I wonder if maybe this line should be followed by a return statement so that this line is not executed anymore?

Note: that is not included in the version of type-cacheable I'm using.

Expected behavior

No Redis SET operation is executed in case of error thrown by the decorated function.

Environment:

  • OS: Windows 11 Pro N
  • Version: "@type-cacheable/core": "^11.0.0"
  • Adapter: "@type-cacheable/ioredis-adapter": "^12.0.1"

[BUG] Wrong Peer Dependencies set

Describe the bug
After the last update of the core, from version 13 to 14, only the adapter's dev dependency were updated, the peer dependencies version were not updated.

To Reproduce
Install the core package and an adapter.

Expected behavior
No problems with the peer dependencies.

Screenshots

Installation made with pnpm:

immagine

Environment:

  • OS: Windows 11 Pro
  • Version: 14.0.0
  • Adapter: all the latest versions, ioredis 15, lru 17, node cache 14, redis 17

Cache hit / miss rate

Love this library!

At the moment there appears to be no hooks to determine if the cached key lookup was a hit or a miss or the number of times a key has been accessed ? Any thoughts on an interface to view these stats?

[BUG] Doesn't work with node-redis 4.1.0

In the node-redis 4.1.0 release, they changed the location of their subpackages. Quoting from their page:

⚠️ In version 4.1.0 we moved our subpackages from @node-redis to @redis. If you're just using npm install redis, you don't need to do anything—it'll upgrade automatically. If you're using the subpackages directly, you'll need to point to the new scope (e.g. @redis/client instead of @node-redis/client).

This doesn't work with the import statement in the redis-adaptor

They really should have incremented the major version for this breaking change, but they didn't.

Caching numeric values

Thank you for this great library, we have been able to make great use of it already!

So far we have been using it for methods that return objects. I wanted to cache a method that returns a number but at the moment it appears that caching a numeric value itself is not supported for the redis adapter. The cached value is returned as a string. This conversion is done on this line in the adapter:
https://github.com/joshuaslate/type-cacheable/blob/master/packages/redis-adapter/lib/index.ts#L232

For numeric/boolean values nested inside an object it looks like the conversion is done by adding an identifier: https://github.com/joshuaslate/type-cacheable/blob/master/packages/redis-adapter/lib/index.ts#L8-L11

Would it make sense to do the same for simple numeric and boolean values? Or drop the JSON.stringify for numbers/booleans?

[bug] ttlseconds is actually using milliseconds and not seconds

No idea if this is a core bug or the lrucache adaptor bug.

I'm using LRUCache. When specifying ttlseconds I have to actually specify millis. e.g for 30 seconds I have to specify

ttlseconds: 30000

It took me a while to work out why caching wasn't working!

Multiple Caches

Hello, quick question. I can't see how you can setup different named caches. For example, if I have 3 different areas e..g products, orders, sales etc, I would want to create a separate cache per functional area. Each area will have different TTL etc. Is this possible or do I need to use one cache and specify a hashkey for each each functional area?

Cheers

Missing changelog

Hi there, big thanks for this lib, it helps us tremendously!
But I need to ask you for a favor, could you always provide a changelog when releasing new version (with warnings for breaking changes ofc)?
It would greatly help everybody using your lib.
Thanks

Property 'setOptions' does not exist on type 'NodeCache'

Following the example from @type-cacheable/node-cache-adapter README and then trying to set options as per core README.

import { CacheManagerOptions, Cacheable } from '@type-cacheable/core';
import { useAdapter } from '@type-cacheable/node-cache-adapter';

import NodeCache from 'node-cache';

const client = new NodeCache();
useAdapter(client);

client.setOptions(<CacheManagerOptions>{
  excludeContext: false,
  ttlSeconds: 0
});

Property 'setOptions' does not exist on type 'NodeCache' typescript error ..

versions.

[BUG] Redis adapter returns string values instead of Date

Describe the bug
Using redis adapter, cache saves Date instance value as a string. Getting cached value returns string instead of Date instance.

To Reproduce
Steps to reproduce the behavior:

@Cacheable({ cacheKey: (args) => args[0], hashKey: 'getDateObject', ttlSeconds: 60 * 60 })
public getDate(anyKey: string): { myDate: Date } {
    return { myDate: new Date() }
  }
  
  public getCachedDate(): void {
  // setting cache first. Returns { myDate: Date }
   const response = this.getDate('some-key')

 // getting data from cache. Returns { myDate: string }
  const wrongResponse = this.getDate('some-key')
}
  

Expected behavior
Response should be consistent, doesn't matter if loaded from cache or not. Should return date if possible

Environment:

  • OS: MacOs, Linux
  • Version 10.0.3
  • Adapter Redis 11.0.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.