Skip to content

Instantly share code, notes, and snippets.

@sancau
Created July 19, 2020 13:35
Show Gist options
  • Save sancau/744496188bd2ead3c7cf2f6dcee86df2 to your computer and use it in GitHub Desktop.
Save sancau/744496188bd2ead3c7cf2f6dcee86df2 to your computer and use it in GitHub Desktop.
Python LRU cache with TTL. Decorator.
import time
from functools import lru_cache
def lru_with_ttl(*, ttl_seconds, maxsize=128):
"""
A decorator to apply LRU in-memory cache to a function with defined maximum(!) TTL in seconds.
Be design an actual TTL may be shorter then the passed value (in rare randomized cases). But it can't be higher.
:param ttl_seconds: TTL for a cache record in seconds
:param maxsize: Maximum size of the LRU cache (a functools.lru_cache argument)
:return: decorated function
"""
def deco(foo):
@lru_cache(maxsize=maxsize)
def cached_with_ttl(*args, ttl_hash, **kwargs):
return foo(*args, **kwargs)
def inner(*args, **kwargs):
return cached_with_ttl(*args, ttl_hash=round(time.time() / ttl_seconds), **kwargs)
return inner
return deco
@nickovs
Copy link

nickovs commented Apr 1, 2023

This is an elegant idea, but it doesn't really implement a proper TTL cache. As it's written it divides the time line into windows of length ttl_seconds and then returns a cached result if the function has already been called with the same arguments in the same time window. This means that if you have a pair of calls in quick succession but one happens to land at the end of a time window and the second happens at the start of the next time window then the cached value is not used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment