Skip to content

Commit fab1358

Browse files
committed
bug fixes
1 parent e243b1b commit fab1358

File tree

9 files changed

+763
-108
lines changed

9 files changed

+763
-108
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensnip/lrujs",
3-
"version": "1.0.8",
3+
"version": "1.0.9",
44
"description": "Fast and lightweight lru cache for javascript",
55
"main": "index.mjs",
66
"type": "module",

src/cache.cjs

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
const LinkedList = require("./linkedlist/index.cjs");
2+
13
module.exports = class Cache {
4+
#linkedList = null;
25
#cache = null;
36
#config = {
47
ttl: 0,
5-
maxLength: 0,
8+
maxLength: 250,
69
interval: 0,
710
intervalId: null,
811
enableInterval: false,
@@ -55,12 +58,12 @@ module.exports = class Cache {
5558
? options.enableInterval
5659
: false;
5760

58-
this.#config.evictionPolicy = options.evictionPolicy;
5961
this.#config.maxLength = options.maxLength;
6062
this.#config.ttl = options.ttl;
6163
this.#config.interval = options.interval;
6264
this.#config.enableInterval =
6365
options.interval > 0 ? options.enableInterval : false;
66+
this.#linkedList = new LinkedList();
6467
this.#cache = new Map();
6568

6669
// Automatically remove expires cache
@@ -72,7 +75,6 @@ module.exports = class Cache {
7275
}
7376

7477
set(key, value, options = {}) {
75-
// Insert a new node at head
7678
if (
7779
(typeof options.ttl !== "undefined" && typeof options.ttl !== "number") ||
7880
options.ttl < 0
@@ -83,31 +85,32 @@ module.exports = class Cache {
8385
options.ttl =
8486
typeof options.ttl === "number" ? options.ttl : this.#config.ttl;
8587

86-
const node = {
88+
const nodeValue = {
8789
key: key,
8890
value: value,
8991
createdAt: Date.now(),
9092
expiresAt: null,
9193
ttl: options.ttl,
9294
frequency: 0,
9395
};
94-
if (node.ttl > 0) {
95-
node.expiresAt = node.createdAt + node.ttl;
96+
if (nodeValue.ttl > 0) {
97+
nodeValue.expiresAt = nodeValue.createdAt + nodeValue.ttl;
9698
}
9799

100+
// Insert a new node at head
101+
const existingNode = this.#cache.get(key);
98102
// Update node data if node is already exists
99-
if (this.#cache.has(key)) {
100-
const existingNode = this.#cache.get(key);
101-
existingNode.value = node.value;
103+
if (typeof existingNode !== "undefined") {
104+
existingNode.value = nodeValue;
102105
// Move current node to the head
103-
this.#cache.delete(key);
104-
this.#cache.set(key, existingNode);
106+
this.#linkedList.setHead(existingNode);
105107
} else {
106108
// Remove node if cache is full
107109
if (this.length === this.#config.maxLength) {
108110
this.#evict();
109111
}
110112
// Create new node and make attach it to the head
113+
const node = this.#linkedList.insertHead(nodeValue);
111114
this.#cache.set(key, node);
112115
}
113116
}
@@ -118,26 +121,26 @@ module.exports = class Cache {
118121
throw new TypeError("callback should be a function");
119122
}
120123

121-
if (this.#cache.has(key)) {
122-
const node = this.#cache.get(key);
124+
const node = this.#cache.get(key);
125+
126+
if (typeof node !== "undefined") {
123127
// Check node is live or not
124128
if (this.#isStale(node)) {
125129
this.delete(key);
126-
throw new Error(key + " key not found");
130+
throw new Error(key + " Key not found");
127131
}
128132

129133
// Move current node to the head
130-
this.#cache.delete(key);
131-
this.#cache.set(key, node);
134+
this.#linkedList.setHead(node);
132135

133136
if (callback) {
134-
return callback(null, node.value);
137+
return callback(null, node.value.value);
135138
} else {
136-
return node.value;
139+
return node.value.value;
137140
}
138141
}
139142

140-
throw new Error(key + " key not found");
143+
throw new Error(key + " Key not found");
141144
} catch (err) {
142145
if (callback) {
143146
return callback(err, undefined);
@@ -148,27 +151,41 @@ module.exports = class Cache {
148151
}
149152

150153
delete(key) {
151-
if (this.#cache.has(key)) {
154+
const node = this.#cache.get(key);
155+
156+
if (typeof node !== "undefined") {
157+
this.#linkedList.delete(node);
152158
// Delete node
153159
this.#cache.delete(key);
154160
}
155161
}
156162

157163
#evict() {
158-
if (this.length === 0) return;
164+
if (this.#linkedList.tail === null) return;
159165
if (this.length !== this.#config.maxLength) return;
160-
161-
for (const key of this.#cache.keys()) {
162-
this.delete(key);
163-
break;
164-
}
166+
this.delete(this.#linkedList.tail.value.key);
165167
}
166168

167169
clear() {
168170
// Delete all data from cache
171+
this.#linkedList.clear();
169172
this.#cache.clear();
170173
}
171174

175+
has(key) {
176+
const node = this.#cache.get(key);
177+
178+
if (typeof node !== "undefined") {
179+
// Check node is live or not
180+
if (this.#isStale(node)) {
181+
this.delete(key);
182+
} else {
183+
return true;
184+
}
185+
}
186+
return false;
187+
}
188+
172189
startInterval() {
173190
// Interval already running
174191
if (this.#config.intervalId) return;
@@ -193,31 +210,21 @@ module.exports = class Cache {
193210
}
194211
}
195212

196-
has(key) {
197-
if (this.#cache.has(key)) {
198-
const node = this.#cache.get(key);
199-
// Check node is live or not
200-
if (this.#isStale(node)) {
201-
this.delete(key);
202-
} else {
203-
return true;
204-
}
205-
}
206-
return false;
207-
}
208-
209213
// Iterate over cache using forEach loop
210214
forEach(callback) {
211215
if (callback && typeof callback !== "function") {
212216
throw new TypeError("callback should be a function");
213217
}
214218

219+
let node = this.#linkedList.head;
215220
let index = 0;
216-
for (const data of this.#cache.entries()) {
217-
if (this.has(data[0])) {
218-
callback({ [data[0]]: data[1].value }, index);
219-
index++;
221+
while (node) {
222+
let next = node.next;
223+
if (this.has(node.value.key)) {
224+
callback({ [node.value.key]: node.value.value }, index);
220225
}
226+
node = next;
227+
index++;
221228
}
222229
}
223230

@@ -230,16 +237,19 @@ module.exports = class Cache {
230237
}
231238

232239
#isStale(node) {
233-
if (!node.expiresAt) return false;
234-
return node.expiresAt - Date.now() <= 0;
240+
if (!node.value.expiresAt) return false;
241+
return node.value.expiresAt - Date.now() <= 0;
235242
}
236243

237244
// Iterator to iterate over cache with a 'for...of' loop
238245
*[Symbol.iterator]() {
239-
for (const data of this.#cache.entries()) {
240-
if (this.has(data[0])) {
241-
yield { [data[0]]: data[1].value };
246+
let node = this.#linkedList.head;
247+
while (node) {
248+
let next = node.next;
249+
if (this.has(node.value.key)) {
250+
yield { [node.value.key]: node.value.value };
242251
}
252+
node = next;
243253
}
244254
}
245255
};

0 commit comments

Comments
 (0)