-
-
Notifications
You must be signed in to change notification settings - Fork 67
/
LocalStore.js
49 lines (40 loc) · 1.37 KB
/
LocalStore.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
'use strict'
const { LruMap: Lru } = require('toad-cache')
function LocalStore (cache = 5000, timeWindow, continueExceeding) {
this.lru = new Lru(cache)
this.timeWindow = timeWindow
this.continueExceeding = continueExceeding
}
LocalStore.prototype.incr = function (ip, cb, max, ban) {
const nowInMs = Date.now()
let current = this.lru.get(ip)
if (!current) {
// Item doesn't exist
current = { current: 1, ttl: this.timeWindow, ban: false, iterationStartMs: nowInMs }
} else if (current.iterationStartMs + this.timeWindow <= nowInMs) {
// Item has expired
current.current = 1
current.ttl = this.timeWindow
current.ban = false
current.iterationStartMs = nowInMs
} else {
// Item is alive
++current.current
// Reset TLL if max has been exceeded and `continueExceeding` is enabled
if (this.continueExceeding && current.current > max) {
current.ttl = this.timeWindow
current.iterationStartMs = nowInMs
} else {
current.ttl = this.timeWindow - (nowInMs - current.iterationStartMs)
}
}
if (ban !== -1 && !current.ban && current.current - max > ban) {
current.ban = true
}
this.lru.set(ip, current)
cb(null, current)
}
LocalStore.prototype.child = function (routeOptions) {
return new LocalStore(routeOptions.cache, routeOptions.timeWindow, routeOptions.continueExceeding)
}
module.exports = LocalStore