-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.py
More file actions
112 lines (90 loc) · 3.21 KB
/
cache.py
File metadata and controls
112 lines (90 loc) · 3.21 KB
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
"""
Simple LRU cache implementation for frequently accessed data.
"""
import threading
import time
from collections import OrderedDict
from typing import Any
class LRUCache:
"""
Thread-safe Least Recently Used (LRU) cache with TTL support.
"""
def __init__(self, max_size: int = 100, ttl: int | None = None):
"""
Initialize LRU cache.
Args:
max_size: Maximum number of items to cache
ttl: Time-to-live in seconds (None for no expiration)
"""
self.max_size = max_size
self.ttl = ttl
self._cache: OrderedDict = OrderedDict()
self._timestamps: dict[str, float] = {}
self._lock = threading.Lock()
self._hits = 0
self._misses = 0
def get(self, key: str) -> Any | None:
"""
Get value from cache.
Args:
key: Cache key
Returns:
Cached value or None if not found/expired
"""
with self._lock:
if key not in self._cache:
self._misses += 1
return None
if self.ttl is not None:
timestamp = self._timestamps.get(key, 0)
if time.time() - timestamp > self.ttl:
del self._cache[key]
del self._timestamps[key]
self._misses += 1
return None
self._cache.move_to_end(key)
self._hits += 1
return self._cache[key]
def set(self, key: str, value: Any):
"""
Set value in cache.
Args:
key: Cache key
value: Value to cache
"""
with self._lock:
if key in self._cache:
self._cache.move_to_end(key)
else:
self._cache[key] = value
if len(self._cache) > self.max_size:
oldest_key = next(iter(self._cache))
del self._cache[oldest_key]
if oldest_key in self._timestamps:
del self._timestamps[oldest_key]
self._cache[key] = value
self._timestamps[key] = time.time()
def invalidate(self, key: str):
"""Remove key from cache."""
with self._lock:
if key in self._cache:
del self._cache[key]
if key in self._timestamps:
del self._timestamps[key]
def clear(self):
"""Clear all cached items."""
with self._lock:
self._cache.clear()
self._timestamps.clear()
self._hits = 0
self._misses = 0
def stats(self) -> dict[str, Any]:
"""Get cache statistics."""
with self._lock:
total = self._hits + self._misses
hit_rate = self._hits / total if total > 0 else 0
return {"size": len(self._cache), "max_size": self.max_size, "hits": self._hits, "misses": self._misses, "hit_rate": hit_rate, "ttl": self.ttl}
project_cache = LRUCache(max_size=50, ttl=300) # 5 minutes TTL
stats_cache = LRUCache(max_size=100, ttl=60) # 1 minute TTL
search_cache = LRUCache(max_size=500, ttl=600) # 10 minutes TTL
file_cache = LRUCache(max_size=200, ttl=300) # 5 minutes TTL