joshuaslate / type-cacheable Goto Github PK
View Code? Open in Web Editor NEWTypeScript-based caching decorator (currently supports Redis, LRU-Cache and NodeCache)
License: MIT License
TypeScript-based caching decorator (currently supports Redis, LRU-Cache and NodeCache)
License: MIT License
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 :
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
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?
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
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.
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.
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?
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) {
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
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
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';
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?
How do clear all keys in a cache using @CacheClear without specifying every key?
It is sometimes useful to blow away the whole cache when an update/delete occurs
Can you explain why having a colon in the cacheKey makes a difference ? (see https://github.com/joshuaslate/type-cacheable/blob/master/lib/adapters/RedisAdapter.ts#L70)
It didn't seem to matter when the value is a Promise of a list, but when it is a Promise of an object, the result is empty if there is a colon in the cacheKey.
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...
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:
Additional context
It's the same problem as this issue #638, except that in this case it is on the IoRedis adapter.
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 ?
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
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
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.
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!
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
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.
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.
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...
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?
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?
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!
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:
Expected behavior
The function is locked until a response is returned and then it's cached.
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 }
Sorry - I didn't appreciate in my recent commits
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>);
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.
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.
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.
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.
Changes are not explained in changelog, can you fix this please? :)
Thanks for awesome library
Hi and thanks for the package!
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.
$ 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
.
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>;
}
type-cacheable
import * as NodeCache from "node-cache";
// Other app setup stuff
const cacheClient = new NodeCache.default();
useNodeCacheAdapter(cacheClient);
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.
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:
"@type-cacheable/core": "^11.0.0"
"@type-cacheable/ioredis-adapter": "^12.0.1"
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:
Environment:
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?
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.
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?
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!
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
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
Right now @type-cacheable/core
indicated in the dependencies
section, because of this, 2 different versions of the package can be installed in the project and nothing will be cached.
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.
type-cacheable/[email protected]
type-cacheable/[email protected]
[email protected]
This would make for a slightly smaller dependency tree.
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:
when cacheKey
is set as an array of string for CacheClear
decorator, it'll only clear out the first key in the array
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.