CodShot
Python Public

Fork: Async LRU Cache with TTL and Eviction Callback

Implements an asynchronous Least Recently Used (LRU) cache with a fixed size, optional time-to-live (TTL) for entries, background expiration cleanup, and support for eviction event callbacks.

Python
import asyncio
import time
from collections import OrderedDict

class AsyncLRUCache:
    def __init__(self, maxsize):
        self.maxsize = maxsize
        self.cache = OrderedDict()  # key -> (value, expire_time)
        self.lock = asyncio.Lock()
        self._eviction_callback = None
        self._cleanup_task = None

    async def get(self, key):
        async with self.lock:
            if key not in self.cache:
                return None
            value, expire = self.cache[key]
            if expire is not None and expire < time.time():
                await self._evict(key, reason='expired')
                return None
            # Move to end to mark as recently used
            self.cache.move_to_end(key)
            return value

    async def set(self, key, value, ttl_sec=None):
        async with self.lock:
            expire = time.time() + ttl_sec if ttl_sec is not None else None
            if key in self.cache:
                self.cache[key] = (value, expire)
                self.cache.move_to_end(key)
            else:
                self.cache[key] = (value, expire)
            if len(self.cache) > self.maxsize:
                oldest_key = next(iter(self.cache))
                await self._evict(oldest_key, reason='capacity')

    async def _evict(self, key, reason):
        if key in self.cache:
            value, expire = self.cache.pop(key)
            if self._eviction_callback:
                await self._maybe_await(self._eviction_callback, key, value, reason)

    async def _maybe_await(self, func, *args, **kwargs):
        result = func(*args, **kwargs)
        if asyncio.iscoroutine(result):
            await result

    def register_eviction_callback(self, callback):
        self._eviction_callback = callback

    async def _cleanup(self):
        while True:
            async with self.lock:
                keys_to_evict = []
                now = time.time()
                for key, (value, expire) in list(self.cache.items()):
                    if expire is not None and expire < now:
                        keys_to_evict.append(key)
                for key in keys_to_evict:
                    await self._evict(key, reason='expired')
            await asyncio.sleep(1)

    def start_auto_cleanup(self):
        if self._cleanup_task is None or self._cleanup_task.done():
            self._cleanup_task = asyncio.create_task(self._cleanup())

    def stop_auto_cleanup(self):
        if self._cleanup_task and not self._cleanup_task.done():
            self._cleanup_task.cancel()

Snippet actions

CodShot user
CodShot user
Updated: 2026-08-06 00:32
Public snippets
0
Forks
CodShot AI Help
Ask about CodShot features, plans, workspace, AI limits, referrals, and public help topics.
Hi! I can help you understand how CodShot works. What would you like to know?
For account-specific or sensitive issues, please open a support ticket. Open support