Skip to content

Commit b474965

Browse files
Merge branch 'master' into farhan-anjum/FSSDK-11148-implement-CMAB-client
2 parents c33c81f + 72048b6 commit b474965

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

optimizely/odp/lru_cache.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ def peek(self, key: K) -> Optional[V]:
9191
element = self.map.get(key)
9292
return element.value if element is not None else None
9393

94+
def remove(self, key: K) -> None:
95+
"""Remove the element associated with the provided key from the cache."""
96+
with self.lock:
97+
self.map.pop(key, None)
98+
9499

95100
@dataclass
96101
class CacheElement(Generic[V]):

tests/test_lru_cache.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,82 @@ def test_reset(self):
130130
cache.save('cow', 'crate')
131131
self.assertEqual(cache.lookup('cow'), 'crate')
132132

133+
def test_remove_non_existent_key(self):
134+
cache = LRUCache(3, 1000)
135+
cache.save("1", 100)
136+
cache.save("2", 200)
137+
138+
cache.remove("3") # Doesn't exist
139+
140+
self.assertEqual(cache.lookup("1"), 100)
141+
self.assertEqual(cache.lookup("2"), 200)
142+
143+
def test_remove_existing_key(self):
144+
cache = LRUCache(3, 1000)
145+
146+
cache.save("1", 100)
147+
cache.save("2", 200)
148+
cache.save("3", 300)
149+
150+
self.assertEqual(cache.lookup("1"), 100)
151+
self.assertEqual(cache.lookup("2"), 200)
152+
self.assertEqual(cache.lookup("3"), 300)
153+
154+
cache.remove("2")
155+
156+
self.assertEqual(cache.lookup("1"), 100)
157+
self.assertIsNone(cache.lookup("2"))
158+
self.assertEqual(cache.lookup("3"), 300)
159+
160+
def test_remove_from_zero_sized_cache(self):
161+
cache = LRUCache(0, 1000)
162+
cache.save("1", 100)
163+
cache.remove("1")
164+
165+
self.assertIsNone(cache.lookup("1"))
166+
167+
def test_remove_and_add_back(self):
168+
cache = LRUCache(3, 1000)
169+
cache.save("1", 100)
170+
cache.save("2", 200)
171+
cache.save("3", 300)
172+
173+
cache.remove("2")
174+
cache.save("2", 201)
175+
176+
self.assertEqual(cache.lookup("1"), 100)
177+
self.assertEqual(cache.lookup("2"), 201)
178+
self.assertEqual(cache.lookup("3"), 300)
179+
180+
def test_thread_safety(self):
181+
import threading
182+
183+
max_size = 100
184+
cache = LRUCache(max_size, 1000)
185+
186+
for i in range(1, max_size + 1):
187+
cache.save(str(i), i * 100)
188+
189+
def remove_key(k):
190+
cache.remove(str(k))
191+
192+
threads = []
193+
for i in range(1, (max_size // 2) + 1):
194+
thread = threading.Thread(target=remove_key, args=(i,))
195+
threads.append(thread)
196+
thread.start()
197+
198+
for thread in threads:
199+
thread.join()
200+
201+
for i in range(1, max_size + 1):
202+
if i <= max_size // 2:
203+
self.assertIsNone(cache.lookup(str(i)))
204+
else:
205+
self.assertEqual(cache.lookup(str(i)), i * 100)
206+
207+
self.assertEqual(len(cache.map), max_size // 2)
208+
133209
# type checker test
134210
# confirm that LRUCache matches OptimizelySegmentsCache protocol
135211
_: OptimizelySegmentsCache = LRUCache(0, 0)

0 commit comments

Comments
 (0)