Created
July 19, 2020 13:35
-
-
Save sancau/744496188bd2ead3c7cf2f6dcee86df2 to your computer and use it in GitHub Desktop.
Python LRU cache with TTL. Decorator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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
may consider decorating
inner
withfunctools.wraps
in case of losing information aboutfoo