Giter Club home page Giter Club logo

ttlcache's People

Contributors

dlebech avatar edsondewes avatar isaacs avatar smacker avatar stimulcross 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

Watchers

 avatar  avatar  avatar

ttlcache's Issues

[BUG] cannot graceful stop due to leaked Timeout

Reproduce

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

Actual

$ time deno run reproduce.ts
real    3m

Expected

$ time deno run reproduce.ts
real    0m

Source

ttlcache/index.js

Lines 78 to 83 in 7317c57

if (!this.expirations[expiration]) {
const t = setTimeout(() => this.purgeStale(), ttl)
/* istanbul ignore else - affordance for non-node envs */
if (t.unref) t.unref()
this.expirations[expiration] = []
}

Also

nodejs also cannot graceful stop due to that leaked Timeout

Feature request: dispose function should be passed the time when an entry would have naturally expired

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!

Feature request: Control over stale entries being emitting before or after collection removal

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:

  • A flag that can dictate whether 'stale' is emitted before or after removal from the collection?
  • A 'pre-stale' event that emits before removal from the collection

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

Module not found: Can't resolve 'perf_hooks'

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'

Steps To Reproduce

  • Create a fresh Next.js (Typescript) application
yarn create next-app my-app --ts
  • Install @isaacs/ttlcache package
yarn add @isaacs/ttlcache
  • Open _app.tsx and create an instance of TTLCache
import "../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;
  • Run yarn dev, open http://localhost:3000 and observe

warn - ./node_modules/@isaacs/ttlcache/index.js
Module not found: Can't resolve 'perf_hooks' in '[...]/node_modules/@isaacs/ttlcache'

bug: deleting an immortal entry causes an error

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 ๐Ÿ™ƒ

TTL = Infinity

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

Iterating entries/keys/values in dispose() function results in undefined entry for the stale element

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:

for (const key of this.expirations[exp]) {

See iteration logic here:

*entries() {

With the current behavior, when I iterate elements in my dispose() function, the first element returns as undefined.

Calling `.clear()` while elements are in the cache causes an exception when they are subsequently attempted to be purged as stale

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)

for (const key of this.expirations[exp]) {

typescript support

The project is not contain any ts declare file, but just infer type by js code. Is there any plan to support it?

purgeStale skips purge due to expiration ceil (assumption) making cache use stale values

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.

Too slow

for (const exp in this.expirations) takes over 200ms to get the first entry when 1e6+ entries exist.

Module not found: Can't resolve 'perf_hooks'

Hi @isaacs, following up #8 (comment), this is my minimal setup to reproduce the warning. Thank you so much for your help.

Step to reproduct

  1. Create a fresh Next.js application
npx create-next-app@latest --typescript myapp
  1. Install @isaacs/ttlcache
npm install @isaacs/ttlcache
  1. Edit myapp/pages/_app.tsx
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
  1. Observe

warn - ./node_modules/@isaacs/ttlcache/index.js
Module not found: Can't resolve 'perf_hooks' in '/.../myapp/node_modules/@isaacs/ttlcache'

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.