1+ const LinkedList = require ( "./linkedlist/index.cjs" ) ;
2+
13module . 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