Django cache illimité sur filesystem – Overrider FileBasedCache


Django propose plusieurs façons de mettre de son site en cache.
Un de nos site gourmant en pages commencait à saturer le cache en mémoire alors il a fallut le basculer sur le filesystem, oui mais Django et son backend filesystem par défaut autorise 300 entrées dans le cache, ensuite il va effacer les anciennes pour les remplacer par les nouvelles, etc…

On peut régler le nombre d’entrées avec l’option MAX_ENTRIES dans les settings mais que fait django derrière ?
Il va scanner votre répertoire de cache et compter tous les fichiers ! Niveau performance on a vu mieux !

Voici un petit patch qui consiste à bypasser le comptage des fichiers dans le cas où l’ont veut un cache “infini”, ce qui soulève un autre problème, ça va cacher jusqu’à qu’il n’y ait plus de pages à cacher ou que le disque sature :)

dans un fichier cache.py que vous mettez où vous voulez (moi dans libs par ex):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
"""
    Override FileBasedCache to extend entries cache count.
    avoid scanning all cache dir to count entries.
 
"""
import os
from django.core.cache.backends.filebased import FileBasedCache
 
class CustomFileBasedCache(FileBasedCache):
 
    def _get_num_entries(self):
       count = 0
       if self._max_entries == 9999: return 0
       for _,_,files in os.walk(self._dir):
           count += len(files)
       return count
    _num_entries = property(_get_num_entries)

dans les settings rajoutez à votre backend filesystem le backend customisé “libs.cache.CustomFileBasedCache” et l’option MAX_ENTRIES à -1:

CACHE_DEFAULT_SECONDS = 3600
CACHES = {
   'default': {
       'BACKEND': 'redis_cache.RedisCache',
       'LOCATION': 'localhost:6379',
       'TIMEOUT': CACHE_DEFAULT_SECONDS,
   },
   'filesystem': {
       'BACKEND': 'libs.cache.CustomFileBasedCache',
       'LOCATION': '/var/tmp/django',
       'TIMEOUT': CACHE_DEFAULT_SECONDS,
       'OPTIONS': {
            'MAX_ENTRIES': 9999 # Set 9999 for unlimited cache
       }
   }
}

On évite du coup le os.walk de la méthode _get_num_entries qui dans le cas d’un grand nombre de fichiers en cache pourrait faire du mal à votre serveur.

A utiliser avec précaution car ça cache, ça cache, ça cache… :)

2 thoughts on “Django cache illimité sur filesystem – Overrider FileBasedCache

  • Sam

    N’oubliez pas une chose: si vous mettez le cache filesystem dans /tmp, il sera effacé au prochain reboot, et votre site devra tout remettre en cache. Soyez bien sûr que c’est ce que vous voulez.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.