1+ import * as crypto from "node:crypto" ;
12import type { CacheData , CacheResult } from "../@types/extension" ;
23
4+ interface CacheEntry extends CacheData {
5+ timestamp : number ;
6+ ttl : number ; // Time to live in milliseconds
7+ }
8+
39export class CacheService {
410 private static _instance : CacheService ;
5- cache : CacheData [ ] = [ ] ;
11+ private cache : Map < string , CacheEntry > = new Map ( ) ;
12+ private readonly DEFAULT_TTL = 5 * 60 * 1000 ; // 5 minutes default TTL
613
714 /**
815 * Returns the singleton instance of the class
@@ -15,39 +22,95 @@ export class CacheService {
1522 return CacheService . _instance ;
1623 }
1724
18- /* A method that takes in a entity and data. It then checks if the record exists and if it
19- doesn't it pushes it to the cache. */
20- public set = ( entity : string , data : string , result : CacheResult ) : void => {
21- if ( ! this . recordExists ( entity , data ) ) {
22- this . cache . push ( {
23- entity : entity ,
24- data : data ,
25- result,
26- } ) ;
25+ /**
26+ * Create a hash key from entity and data for efficient lookups
27+ */
28+ private createHashKey ( entity : string , data : string ) : string {
29+ // Use SHA-256 hash for long diff content to avoid memory issues with large keys
30+ const hash = crypto . createHash ( "sha256" ) ;
31+ hash . update ( `${ entity } :${ data } ` ) ;
32+ return hash . digest ( "hex" ) ;
33+ }
34+
35+ /**
36+ * Clean expired cache entries
37+ */
38+ private cleanExpired ( ) : void {
39+ const now = Date . now ( ) ;
40+ for ( const [ key , entry ] of this . cache . entries ( ) ) {
41+ if ( now - entry . timestamp > entry . ttl ) {
42+ this . cache . delete ( key ) ;
43+ }
44+ }
45+ }
46+
47+ /**
48+ * Set a cache entry with optional TTL
49+ */
50+ public set = ( entity : string , data : string , result : CacheResult , ttl ?: number ) : void => {
51+ const key = this . createHashKey ( entity , data ) ;
52+
53+ // Clean expired entries periodically (every 10th set operation)
54+ if ( this . cache . size % 10 === 0 ) {
55+ this . cleanExpired ( ) ;
2756 }
57+
58+ this . cache . set ( key , {
59+ entity,
60+ data,
61+ result,
62+ timestamp : Date . now ( ) ,
63+ ttl : ttl || this . DEFAULT_TTL ,
64+ } ) ;
2865 } ;
2966
30- /* A method that takes in entity and data. It then checks if the record exists and if it
31- doesn't it pushes it to the cache. */
67+ /**
68+ * Get a cache entry if it exists and hasn't expired
69+ */
3270 public get = ( entity : string , data : string ) : CacheResult | null => {
33- const cacheRecord = this . cache . find ( ( x ) => {
34- if ( data ) {
35- return x . entity === entity && x . data === data ;
36- }
71+ const key = this . createHashKey ( entity , data ) ;
72+ const entry = this . cache . get ( key ) ;
3773
38- return x . entity === entity ;
39- } ) ;
74+ if ( ! entry ) {
75+ return null ;
76+ }
4077
41- if ( cacheRecord ) {
42- return cacheRecord . result ;
78+ // Check if entry has expired
79+ const now = Date . now ( ) ;
80+ if ( now - entry . timestamp > entry . ttl ) {
81+ this . cache . delete ( key ) ;
82+ return null ;
4383 }
4484
45- return null ;
85+ return entry . result ;
4686 } ;
4787
48- /* It's a method that takes in entity and data . It then checks if the record exists and if it
49- doesn't it pushes it to the cache. */
88+ /**
89+ * Check if a cache record exists and is valid
90+ */
5091 public recordExists = ( entity : string , data : string ) : boolean => {
51- return ! ! this . get ( entity , data ) ;
92+ return this . get ( entity , data ) !== null ;
93+ } ;
94+
95+ /**
96+ * Clear all cache entries
97+ */
98+ public clear = ( ) : void => {
99+ this . cache . clear ( ) ;
100+ } ;
101+
102+ /**
103+ * Get cache statistics
104+ */
105+ public getStats = ( ) => {
106+ return {
107+ size : this . cache . size ,
108+ entries : Array . from ( this . cache . values ( ) ) . map ( ( entry ) => ( {
109+ entity : entry . entity ,
110+ timestamp : entry . timestamp ,
111+ ttl : entry . ttl ,
112+ expired : Date . now ( ) - entry . timestamp > entry . ttl ,
113+ } ) ) ,
114+ } ;
52115 } ;
53116}
0 commit comments