File size: 3,082 Bytes
69b897d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
 * LRU (Least Recently Used) 缓存实现
 * 用于缓存解密结果,提高性能同时控制内存使用
 */
class LRUCache {
  constructor(maxSize = 500) {
    this.maxSize = maxSize
    this.cache = new Map()
    this.hits = 0
    this.misses = 0
    this.evictions = 0
    this.lastCleanup = Date.now()
    this.cleanupInterval = 5 * 60 * 1000 // 5分钟清理一次过期项
  }

  /**
   * 获取缓存值
   * @param {string} key - 缓存键
   * @returns {*} 缓存的值,如果不存在则返回 undefined
   */
  get(key) {
    // 定期清理
    if (Date.now() - this.lastCleanup > this.cleanupInterval) {
      this.cleanup()
    }

    const item = this.cache.get(key)
    if (!item) {
      this.misses++
      return undefined
    }

    // 检查是否过期
    if (item.expiry && Date.now() > item.expiry) {
      this.cache.delete(key)
      this.misses++
      return undefined
    }

    // 更新访问时间,将元素移到最后(最近使用)
    this.cache.delete(key)
    this.cache.set(key, {
      ...item,
      lastAccessed: Date.now()
    })

    this.hits++
    return item.value
  }

  /**
   * 设置缓存值
   * @param {string} key - 缓存键
   * @param {*} value - 要缓存的值
   * @param {number} ttl - 生存时间(毫秒),默认5分钟
   */
  set(key, value, ttl = 5 * 60 * 1000) {
    // 如果缓存已满,删除最少使用的项
    if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
      const firstKey = this.cache.keys().next().value
      this.cache.delete(firstKey)
      this.evictions++
    }

    this.cache.set(key, {
      value,
      createdAt: Date.now(),
      lastAccessed: Date.now(),
      expiry: ttl ? Date.now() + ttl : null
    })
  }

  /**
   * 清理过期项
   */
  cleanup() {
    const now = Date.now()
    let cleanedCount = 0

    for (const [key, item] of this.cache.entries()) {
      if (item.expiry && now > item.expiry) {
        this.cache.delete(key)
        cleanedCount++
      }
    }

    this.lastCleanup = now
    if (cleanedCount > 0) {
      console.log(`🧹 LRU Cache: Cleaned ${cleanedCount} expired items`)
    }
  }

  /**
   * 清空缓存
   */
  clear() {
    const { size } = this.cache
    this.cache.clear()
    this.hits = 0
    this.misses = 0
    this.evictions = 0
    console.log(`🗑️ LRU Cache: Cleared ${size} items`)
  }

  /**
   * 获取缓存统计信息
   */
  getStats() {
    const total = this.hits + this.misses
    const hitRate = total > 0 ? ((this.hits / total) * 100).toFixed(2) : 0

    return {
      size: this.cache.size,
      maxSize: this.maxSize,
      hits: this.hits,
      misses: this.misses,
      evictions: this.evictions,
      hitRate: `${hitRate}%`,
      total
    }
  }

  /**
   * 打印缓存统计信息
   */
  printStats() {
    const stats = this.getStats()
    console.log(
      `📊 LRU Cache Stats: Size: ${stats.size}/${stats.maxSize}, Hit Rate: ${stats.hitRate}, Hits: ${stats.hits}, Misses: ${stats.misses}, Evictions: ${stats.evictions}`
    )
  }
}

module.exports = LRUCache