Skip to content

Commit 06103f2

Browse files
committed
feat: replace LRU with simpler cache
1 parent 50077ae commit 06103f2

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

modules/MatcherCache.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Simple cache - NEW cached items are added to cachedKeys array. When cache is
2+
// full, oldest key is removed from array and item is removed from cache
3+
4+
const DEFAULT_OPTIONS = {
5+
limit: 200
6+
}
7+
8+
export default class MatcherCache {
9+
cache = {}
10+
cachedKeys = []
11+
12+
constructor(options = {}) {
13+
const mergedOptions = {
14+
...DEFAULT_OPTIONS,
15+
...options
16+
}
17+
this.options = mergedOptions
18+
}
19+
20+
set(key, value) {
21+
// If this key is not cached add key to cachedKeys array
22+
if (this.cache[key] === undefined) {
23+
this.cachedKeys.push(key)
24+
}
25+
this.cache[key] = value
26+
this.checkCacheLimit()
27+
}
28+
29+
get(key) {
30+
return this.cache[key]
31+
}
32+
33+
checkCacheLimit() {
34+
// Clear a cache item if we are over limit
35+
if (this.cachedKeys.length > this.options.limit) {
36+
const keyToUncache = this.cachedKeys.shift()
37+
delete this.cache[keyToUncache]
38+
}
39+
}
40+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import expect from 'expect'
2+
import MatcherCache from '../MatcherCache'
3+
4+
describe('MatcherCache', () => {
5+
let cache
6+
7+
beforeEach(() => {
8+
cache = new MatcherCache({ limit: 1 })
9+
})
10+
11+
it('can set and get an item', () => {
12+
cache.set('/url', 1)
13+
expect(cache.get('/url')).toEqual(1)
14+
})
15+
16+
it('removes cached item when limit is reached', () => {
17+
cache.set('/url-1', 1)
18+
cache.set('/url-2', 2)
19+
expect(cache.get('/url-1')).toEqual(undefined)
20+
expect(cache.get('/url-2')).toEqual(2)
21+
})
22+
23+
it('should override currently cached items', () => {
24+
cache.set('/url-1', 1)
25+
cache.set('/url-1', 2)
26+
expect(cache.get('/url-1')).toEqual(2)
27+
expect(cache.cachedKeys.length).toEqual(1)
28+
})
29+
})

modules/matchPattern.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import pathToRegexp from 'path-to-regexp'
2+
import MatcherCache from './MatcherCache'
23

34
// cache[exactly][pattern] contains getMatcher(pattern, exactly)
4-
const cache = {true: {}, false: {}}
5+
const cache = {
6+
true: new MatcherCache(),
7+
false: new MatcherCache()
8+
}
59

610
const getMatcher = (pattern, exactly) => {
711
const exactlyStr = exactly ? 'true' : 'false'
8-
let matcher = cache[exactlyStr][pattern]
12+
let matcher = cache[exactlyStr].get(pattern)
913

1014
if (!matcher) {
1115
const keys = []
1216
const regex = pathToRegexp(pattern, keys, { end: exactly, strict: true })
13-
matcher = cache[exactlyStr][pattern] = { keys, regex }
17+
matcher = { keys, regex }
18+
cache[exactlyStr].set(pattern, matcher)
1419
}
1520

1621
return matcher

0 commit comments

Comments
 (0)