Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: isaacs/node-lru-cache
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v7.13.2
Choose a base ref
...
head repository: isaacs/node-lru-cache
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v7.14.0
Choose a head ref
  • 2 commits
  • 8 files changed
  • 1 contributor

Commits on Aug 16, 2022

  1. add maxEntrySize option

    Re: #252
    isaacs committed Aug 16, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3ef4a76 View commit details
  2. 7.14.0

    isaacs committed Aug 16, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    97d1e2d View commit details
Showing with 102 additions and 13 deletions.
  1. +5 −0 CHANGELOG.md
  2. +15 −2 README.md
  3. +10 −1 index.d.ts
  4. +18 −7 index.js
  5. +2 −2 package-lock.json
  6. +1 −1 package.json
  7. +5 −0 test/basic.ts
  8. +46 −0 test/size-calculation.ts
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# cringe lorg

## 7.14.0

* Add `maxEntrySize` option to prevent caching items above a
given calculated size.

## 7.13.0

* Add `forceRefresh` option to trigger a call to the
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -118,8 +118,10 @@ Attempting to add an item to the cache whose calculated size is
greater that this amount will be a no-op. The item will not be
cached, and no other items will be evicted.

Optional, must be a positive integer if provided. Required if
other size tracking features are used.
Optional, must be a positive integer if provided.

Sets `maxItemSize` to the same value, unless a different value is
provided for `maxItemSize`.

At least one of `max`, `maxSize`, or `TTL` is required. This
must be a positive integer if set.
@@ -128,6 +130,17 @@ Even if size tracking is enabled, **it is strongly recommended to
set a `max` to prevent unbounded growth of the cache.** See
"Storage Bounds Safety" below.

### `maxEntrySize`

Set to a positive integer to track the sizes of items added to
the cache, and prevent caching any item over a given size.
Attempting to add an item whose calculated size is greater than
this amount will be a no-op. The item will not be cached, and no
other items will be evicted.

Optional, must be a positive integer if provided. Defaults to
the value of `maxSize` if provided.

### `sizeCalculation`

Function used to calculate the size of stored items. If you're
11 changes: 10 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ declare class LRUCache<K, V> implements Iterable<[K, V]> {

public readonly max: number
public readonly maxSize: number
public readonly maxEntrySize: number
public readonly sizeCalculation:
| LRUCache.SizeCalculator<K, V>
| undefined
@@ -320,6 +321,13 @@ declare namespace LRUCache {
max: number
}

type MaybeMaxEntrySizeLimit<K, V> =
| {
maxEntrySize: number
sizeCalculation?: SizeCalculator<K, V>
}
| {}

interface LimitedBySize<K, V> {
/**
* If you wish to track item size, you must provide a maxSize
@@ -507,7 +515,8 @@ declare namespace LRUCache {

type Options<K, V> = SharedOptions<K, V> &
DeprecatedOptions<K, V> &
SafetyBounds<K, V>
SafetyBounds<K, V> &
MaybeMaxEntrySizeLimit<K, V>

/**
* options which override the options set in the LRUCache constructor
25 changes: 18 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -157,6 +157,7 @@ class LRUCache {
noDisposeOnSet,
noUpdateTTL,
maxSize = 0,
maxEntrySize = 0,
sizeCalculation,
fetchMethod,
fetchContext,
@@ -180,11 +181,12 @@ class LRUCache {

this.max = max
this.maxSize = maxSize
this.maxEntrySize = maxEntrySize || this.maxSize
this.sizeCalculation = sizeCalculation || length
if (this.sizeCalculation) {
if (!this.maxSize) {
if (!this.maxSize && !this.maxEntrySize) {
throw new TypeError(
'cannot set sizeCalculation without setting maxSize'
'cannot set sizeCalculation without setting maxSize or maxEntrySize'
)
}
if (typeof this.sizeCalculation !== 'function') {
@@ -231,10 +233,18 @@ class LRUCache {
this.noUpdateTTL = !!noUpdateTTL
this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection

if (this.maxSize !== 0) {
if (!isPosInt(this.maxSize)) {
// NB: maxEntrySize is set to maxSize if it's set
if (this.maxEntrySize !== 0) {
if (this.maxSize !== 0) {
if (!isPosInt(this.maxSize)) {
throw new TypeError(
'maxSize must be a positive integer if specified'
)
}
}
if (!isPosInt(this.maxEntrySize)) {
throw new TypeError(
'maxSize must be a positive integer if specified'
'maxEntrySize must be a positive integer if specified'
)
}
this.initializeSizeTracking()
@@ -402,7 +412,7 @@ class LRUCache {
requireSize(k, v, size, sizeCalculation) {
if (size || sizeCalculation) {
throw new TypeError(
'cannot set size without setting maxSize on cache'
'cannot set size without setting maxSize or maxEntrySize on cache'
)
}
}
@@ -574,7 +584,8 @@ class LRUCache {
) {
size = this.requireSize(k, v, size, sizeCalculation)
// if the item doesn't fit, don't do anything
if (this.maxSize && size > this.maxSize) {
// NB: maxEntrySize set to maxSize by default
if (this.maxEntrySize && size > this.maxEntrySize) {
return this
}
let index = this.size === 0 ? undefined : this.keyMap.get(k)
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
"version": "7.13.2",
"version": "7.14.0",
"author": "Isaac Z. Schlueter <i@izs.me>",
"keywords": [
"mru",
5 changes: 5 additions & 0 deletions test/basic.ts
Original file line number Diff line number Diff line change
@@ -145,6 +145,11 @@ t.test('setting ttl with non-integer values', t => {
t.test('setting maxSize with non-integer values', t => {
t.throws(() => new LRU({ max: 10, maxSize: 10.5 }), TypeError)
t.throws(() => new LRU({ max: 10, maxSize: -10 }), TypeError)
t.throws(() => new LRU({ max: 10, maxEntrySize: 10.5 }), TypeError)
t.throws(() => new LRU({ max: 10, maxEntrySize: -10 }), TypeError)
// @ts-expect-error
t.throws(() => new LRU({ max: 10, maxEntrySize: 'banana' }), TypeError)
t.throws(() => new LRU({ max: 10, maxEntrySize: Infinity }), TypeError)
// @ts-expect-error
t.throws(() => new LRU({ max: 10, maxSize: 'banana' }), TypeError)
t.throws(() => new LRU({ max: 10, maxSize: Infinity }), TypeError)
46 changes: 46 additions & 0 deletions test/size-calculation.ts
Original file line number Diff line number Diff line change
@@ -196,3 +196,49 @@ t.test('large item falls out of cache, sizes are kept correct', t => {

t.end()
})

t.test('large item falls out of cache because maxEntrySize', t => {
const c = new LRU<number, number>({
maxSize: 1000,
maxEntrySize: 10,
sizeCalculation: () => 100,
})
const sizes:number[] = (c as unknown as { sizes: number[] }).sizes

checkSize(c)
t.equal(c.size, 0)
t.equal(c.calculatedSize, 0)
t.same(sizes, [])

c.set(2, 2, { size: 2 })
checkSize(c)
t.equal(c.size, 1)
t.equal(c.calculatedSize, 2)
t.same(sizes, [2])

c.delete(2)
checkSize(c)
t.equal(c.size, 0)
t.equal(c.calculatedSize, 0)
t.same(sizes, [0])

c.set(1, 1)
checkSize(c)
t.equal(c.size, 0)
t.equal(c.calculatedSize, 0)
t.same(sizes, [0])

c.set(3, 3, { size: 3 })
checkSize(c)
t.equal(c.size, 1)
t.equal(c.calculatedSize, 3)
t.same(sizes, [3])

c.set(4, 4)
checkSize(c)
t.equal(c.size, 1)
t.equal(c.calculatedSize, 3)
t.same(sizes, [3])

t.end()
})