-
Notifications
You must be signed in to change notification settings - Fork 29
/
cache.js
105 lines (86 loc) · 2.12 KB
/
cache.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
var cache = {
// domain => object:
// - ips: array of strings
// - created: Date.now()
// - visited: Date.now()
_items: {},
_length: 0,
// In seconds.
defaultCacheTTL: 600,
maxLength: 1000,
onIpChange: function (domain, ips, existed) { },
onDomainDelete: function (domain) { },
has: function (domain) {
return domain in cache._items;
},
_get: function (domain) {
return cache._items[domain];
},
ips: function (domain) {
var item = cache._get(domain);
if (item) {
return item.ips.concat([]);
}
},
// Empty ips means the domain was resolved as NX.
set: function (domain, ips) {
if (toString.call(domain) != '[object String]' || !domain.match(/^[\w\-.]+$/)
|| !Array.isArray(ips)) {
throw 'BDNS: cache.set(): bad argument(s)';
}
var existed = cache.has(domain);
cache._items[domain] = {
ips: ips.concat([]),
created: Date.now(),
visited: Date.now()
};
cache._length += !existed;
cache.onIpChange(domain, ips, existed);
cache.each(function (domain) {
if (cache._length <= cache.maxLength) { return true; }
cache.delete(domain);
});
},
isExpired: function (domain, ttl) {
var item = cache._get(domain);
if (item) {
return item.visited < Date.now() - ttl * 1000;
}
},
setVisited: function (domain) {
var item = cache._get(domain);
if (item) {
item.visited = Date.now();
}
},
delete: function (domain) {
if (cache.has(domain)) {
delete cache._items[domain];
cache._length--;
cache.onDomainDelete(domain);
return true;
}
},
prune: function (ttl) {
ttl = ttl || cache.defaultCacheTTL;
var threshold = Date.now() - ttl * 1000;
var count = 0;
cache.each(function (domain) {
if (cache._items[domain].visited < threshold) {
count++;
cache.delete(domain);
}
});
return count;
},
each: function (iter) {
for (var domain in cache._items) {
if (iter(domain, cache._items[domain]) === true) {
break;
}
}
},
get length() {
return cache._length;
},
};