Spaces:
Sleeping
Sleeping
import uuid | |
from typing import Any, Callable | |
from chromadb.types import Segment | |
from overrides import override | |
from typing import Dict, Optional | |
from abc import ABC, abstractmethod | |
class SegmentCache(ABC): | |
def get(self, key: uuid.UUID) -> Optional[Segment]: | |
pass | |
def pop(self, key: uuid.UUID) -> Optional[Segment]: | |
pass | |
def set(self, key: uuid.UUID, value: Segment) -> None: | |
pass | |
def reset(self) -> None: | |
pass | |
class BasicCache(SegmentCache): | |
def __init__(self): | |
self.cache:Dict[uuid.UUID, Segment] = {} | |
def get(self, key: uuid.UUID) -> Optional[Segment]: | |
return self.cache.get(key) | |
def pop(self, key: uuid.UUID) -> Optional[Segment]: | |
return self.cache.pop(key, None) | |
def set(self, key: uuid.UUID, value: Segment) -> None: | |
self.cache[key] = value | |
def reset(self) -> None: | |
self.cache = {} | |
class SegmentLRUCache(BasicCache): | |
"""A simple LRU cache implementation that handles objects with dynamic sizes. | |
The size of each object is determined by a user-provided size function.""" | |
def __init__(self, capacity: int, size_func: Callable[[uuid.UUID], int], | |
callback: Optional[Callable[[uuid.UUID, Segment], Any]] = None): | |
self.capacity = capacity | |
self.size_func = size_func | |
self.cache: Dict[uuid.UUID, Segment] = {} | |
self.history = [] | |
self.callback = callback | |
def _upsert_key(self, key: uuid.UUID): | |
if key in self.history: | |
self.history.remove(key) | |
self.history.append(key) | |
else: | |
self.history.append(key) | |
def get(self, key: uuid.UUID) -> Optional[Segment]: | |
self._upsert_key(key) | |
if key in self.cache: | |
return self.cache[key] | |
else: | |
return None | |
def pop(self, key: uuid.UUID) -> Optional[Segment]: | |
if key in self.history: | |
self.history.remove(key) | |
return self.cache.pop(key, None) | |
def set(self, key: uuid.UUID, value: Segment) -> None: | |
if key in self.cache: | |
return | |
item_size = self.size_func(key) | |
key_sizes = {key: self.size_func(key) for key in self.cache} | |
total_size = sum(key_sizes.values()) | |
index = 0 | |
# Evict items if capacity is exceeded | |
while total_size + item_size > self.capacity and len(self.history) > index: | |
key_delete = self.history[index] | |
if key_delete in self.cache: | |
self.callback(key_delete, self.cache[key_delete]) | |
del self.cache[key_delete] | |
total_size -= key_sizes[key_delete] | |
index += 1 | |
self.cache[key] = value | |
self._upsert_key(key) | |
def reset(self): | |
self.cache = {} | |
self.history = [] | |