isaacs / ttlcache Goto Github PK
View Code? Open in Web Editor NEWLicense: ISC License
License: ISC License
import TTLCache from "https://esm.sh/@isaacs/[email protected]";
const cache = new TTLCache({
max: 10000,
ttl: 1000,
})
cache.set('a', 'b', {ttl: 180000})
cache.clear()
$ time deno run reproduce.ts
real 3m
$ time deno run reproduce.ts
real 0m
Lines 78 to 83 in 7317c57
nodejs also cannot graceful stop due to that leaked Timeout
I have a use case where I need to know, if an entry is evicted because the cache is full, what time that entry would have naturally expired. Thus, I would like to change the signature of the dispose callback function from:
dispose(value, key, reason)
to
dispose(value, key, reason, expirationTime)
where expirationTime is the time, in milliseconds since the epoch, when the entry would have naturally expired. Of course, if reason is 'stale' then expirationTime isn't that useful, but if reason is 'set', 'evict' or 'delete' then there are use cases where expirationTime could be valuable.
Right now I can work around this by just setting the value to an object that includes the expiration time, but it would be cleaner/more accurate if I could get the expirationTime directly in the dispose method.
I looked through the source and this should be an easy change. I'm happy to submit a PR for it if you think this feature request is a good idea, but wanted to check with you first. I think this change should be considered backwards compatible as it's just passing an additional parameter to dispose (previously existing dispose functions would just ignore the expirationTime).
Thanks for a great and useful library!
First, thank you so much for your fast resolution of #16 and #17. I see that dispose is emitting 'stale'
only after it is fully removed from the collection now.
With that said, is there any possibility of implementing at least one of the two:
'stale'
is emitted before or after removal from the collection?'pre-stale'
event that emits before removal from the collectionFor now, I can just collect the value removed from the argument in my dispose()
function, but having it in the collection for simple iteration would be nice in my use case.
I tried to integrate this ttlcache into a Next.js (Typescript) project and receive this error:
Module not found: Can't resolve 'perf_hooks' in '[...]/node_modules/@isaacs/ttlcache'
yarn create next-app my-app --ts
@isaacs/ttlcache
packageyarn add @isaacs/ttlcache
_app.tsx
and create an instance of TTLCacheimport "../styles/globals.css";
import type { AppProps } from "next/app";
import TTLCache from "@isaacs/ttlcache";
const cache = new TTLCache({ max: 10, ttl: 1000 });
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default MyApp;
yarn dev
, open http://localhost:3000
and observewarn - ./node_modules/@isaacs/ttlcache/index.js
Module not found: Can't resolve 'perf_hooks' in '[...]/node_modules/@isaacs/ttlcache'
When I try to delete an immortal entry (set with Infinity
TTL) I get the following error:
"C:\Program Files\nodejs\node.exe" C:\Dev\ttlcache\test.js
C:\Dev\ttlcache\index.js:164
this.expirations[current] = exp.filter(k => k !== key)
^
TypeError: Cannot read properties of undefined (reading 'filter')
at TTLCache.delete (C:\Dev\ttlcache\index.js:164:41)
at Object.<anonymous> (C:\Dev\ttlcache\test.js:6:25)
at Module._compile (node:internal/modules/cjs/loader:1149:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
at Module.load (node:internal/modules/cjs/loader:1027:32)
at Module._load (node:internal/modules/cjs/loader:868:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:23:47
Node.js v18.10.0
Process finished with exit code 1
Code to reproduce the issue:
const TtlCache = require('@isaacs/ttlcache');
const cache = new TtlCache({ttl: Infinity});
cache.set('key', 'val');
cache.delete('key');
Entries with TTL set to Infinity
is not present in the expirations
object and the exp
const can be undefined
which causes the error.
So I fixed it and added a test for such a case. I will link a PR
Hello and thanks for this package.
I'd like to propose that TTL could be set to Infinity
pretty much same as for the max
config param.
This would let setting some items as "pinned" into a TTL cache mechanism.
Thanks again,
Marco
In the purgeStale()
method, you can see it deletes map entries from this.data
and this.expirationMap
before calling this.dispose()
, but it leaves the entry in this.expirations
until after that call finishes. This has to be refactored somehow to also remove the entry from this.expirations
before calling this.dispose()
.
See expiration logic here:
Line 204 in 1fe7733
See iteration logic here:
Line 214 in 1fe7733
With the current behavior, when I iterate elements in my dispose() function, the first element returns as undefined
.
TypeError: this.expirations[exp] is not iterable
at TTLCache.purgeStale (node_modules/@isaacs/ttlcache/index.js:204:41)
at Timeout._onTimeout (node_modules/@isaacs/ttlcache/index.js:79:41)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
Line 204 in 1fe7733
The project is not contain any ts declare file, but just infer type by js code. Is there any plan to support it?
I am trying to set up API rate limiter using ttlcache:
const requestsCountByKeyCache = new TTLCache({
ttl: thresholdPeriodInSeconds * 1000,
noUpdateTTL: true,
});
The idea is that requests keep coming in, and I count them using some key, e.g. API_TOKEN_xxxx
. I do not refresh TTL and let them expire, value will reset automatically.
And yet I am hitting rate limit errors. I've set limit to 3 and sending 2 request per second, here is the log:
2022-06-29T06:04:41.811Z API_TOKEN_my.app 1
2022-06-29T06:04:41.812Z API_TOKEN_my.app 2
2022-06-29T06:04:42.812Z purgeStale
2022-06-29T06:04:42.812Z purge done, current value: 2 new data Map(0) {}
2022-06-29T06:04:42.815Z API_TOKEN_my.app 1
2022-06-29T06:04:42.817Z API_TOKEN_my.app 2
2022-06-29T06:04:43.809Z API_TOKEN_my.app 3
2022-06-29T06:04:43.811Z API_TOKEN_my.app 4
2022-06-29T06:04:43.814Z purgeStale
2022-06-29T06:04:43.814Z purgeStale, exp > n 8470 8468.831500053406
2022-06-29T06:04:44.809Z API_TOKEN_my.app 5
2022-06-29T06:04:44.810Z API_TOKEN_my.app 6
2022-06-29T06:04:45.810Z purgeStale
2022-06-29T06:04:45.811Z purge done, current value: 6 new data Map(0) {}
purgeStale, exp > n 8470 8468.831500053406
<- here we skip resetting data and it seems the next one will be queued upon next set
. And no checks are done while getting value from the cache.
Thank you very much for your work.
for (const exp in this.expirations)
takes over 200ms to get the first entry when 1e6+ entries exist.
Hi @isaacs, following up #8 (comment), this is my minimal setup to reproduce the warning. Thank you so much for your help.
npx create-next-app@latest --typescript myapp
npm install @isaacs/ttlcache
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import TTLCache from '@isaacs/ttlcache'
const cache = new TTLCache({ max: 10000, ttl: 1000 })
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default MyApp
warn - ./node_modules/@isaacs/ttlcache/index.js
Module not found: Can't resolve 'perf_hooks' in '/.../myapp/node_modules/@isaacs/ttlcache'
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.