]> git.ipfire.org Git - people/ric9/ipfire.org.git/commitdiff
cache: Remove avatars/images from cache if not used
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 25 Jan 2024 11:41:55 +0000 (11:41 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 25 Jan 2024 11:42:45 +0000 (11:42 +0000)
This creates a simple LRU policy to evict items from the cache that have
not been accessed in 24 hours.

Fixes: #13547
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/backend/accounts.py
src/backend/wiki.py
src/web/users.py

index 9df7d627acd8ff02be20ac8c0f859a4ae5098049..397f217c2a8c32f40466d98bf397ad60f4802d87 100644 (file)
@@ -1301,11 +1301,21 @@ class Account(LDAPObject):
                        return photo
 
                # Compose the cache key
-               key = "accounts:%s:avatar:%s:%s:%s" \
+               cache_key = "accounts:%s:avatar:%s:%s:%s" \
                        % (self.uid, self.avatar_hash, format or "N/A", size)
 
-               # Try to retrieve something from the cache
-               avatar = await self.backend.cache.get(key)
+               # Try to fetch the data from the cache
+               async with await self.backend.cache.pipeline() as p:
+                       # Fetch the key
+                       await p.get(cache_key)
+
+                       # Reset the TTL
+                       await p.expire(cache_key, 86400)
+
+                       # Execute the pipeline
+                       avatar, _ = await p.execute()
+
+               # Return the cached value (if any)
                if avatar:
                        return avatar
 
@@ -1313,7 +1323,7 @@ class Account(LDAPObject):
                avatar = util.generate_thumbnail(photo, size, square=True, format=format)
 
                # Save to cache for 24h
-               await self.backend.cache.set(key, avatar, 86400)
+               await self.backend.cache.set(cache_key, avatar, 86400)
 
                return avatar
 
index 7ef214016da9e78f56bfc18702af9792349c6178..9c5f55aa72180a4e09676209a3a470e993c58f8a 100644 (file)
@@ -713,6 +713,9 @@ class File(misc.Object):
        async def get_thumbnail(self, size, format=None):
                assert self.is_bitmap_image()
 
+               # Let thumbnails live in the cache for up to 24h
+               ttl = 24 * 3600
+
                cache_key = ":".join((
                        "wiki",
                        "thumbnail",
@@ -724,15 +727,25 @@ class File(misc.Object):
                ))
 
                # Try to fetch the data from the cache
-               thumbnail = await self.backend.cache.get(cache_key)
+               async with await self.backend.cache.pipeline() as p:
+                       # Fetch the key
+                       await p.get(cache_key)
+
+                       # Reset the TTL
+                       await p.expire(cache_key, ttl)
+
+                       # Execute the pipeline
+                       thumbnail, _ = await p.execute()
+
+               # Return the cached value
                if thumbnail:
                        return thumbnail
 
                # Generate the thumbnail
                thumbnail = util.generate_thumbnail(self.blob, size, format=format, quality=95)
 
-               # Put it into the cache for forever
-               await self.backend.cache.set(cache_key, thumbnail)
+               # Put it into the cache for 24h
+               await self.backend.cache.set(cache_key, thumbnail, ttl)
 
                return thumbnail
 
index b27c09a2bce539ec99f244a4594975926b3007ae..bc4e57f94917897f076996d805f6db8743790e58 100644 (file)
@@ -93,15 +93,24 @@ class AvatarHandler(base.BaseHandler):
                        size = 2048
 
                # Cache key
-               key = "avatar:letter:%s:%s:%s" % ("".join(letters), format or "N/A", size)
+               cache_key = "avatar:letter:%s:%s:%s" % ("".join(letters), format or "N/A", size)
+
+               # Try to fetch the data from the cache
+               async with await self.backend.cache.pipeline() as p:
+                       # Fetch the key
+                       await p.get(cache_key)
+
+                       # Reset the TTL
+                       await p.expire(cache_key, 86400)
+
+                       # Execute the pipeline
+                       avatar, _ = await p.execute()
 
-               # Fetch avatar from the cache
-               avatar = await self.backend.cache.get(key)
                if not avatar:
                        avatar = self._make_avatar(letters, size=size, **args)
 
                        # Cache for forever
-                       await self.backend.cache.set(key, avatar)
+                       await self.backend.cache.set(cache_key, avatar, 86400)
 
                return avatar