from django.db.models import F from . import threadstore CACHE_KEY = 'misago_cachebuster' class CacheBusterController(object): def register_cache(self, cache): from .models import CacheVersion CacheVersion.objects.create(cache=cache) def unregister_cache(self, cache): from .models import CacheVersion try: cache = CacheVersion.objects.get(cache=cache) cache.delete() except CacheVersion.DoesNotExist: raise ValueError('Cache "%s" is not registered' % cache) @property def cache(self): return self.read_threadstore() def read_threadstore(self): data = threadstore.get(CACHE_KEY, 'nada') if data == 'nada': data = self.read_cache() threadstore.set(CACHE_KEY, data) return data def read_cache(self): from .cache import cache as default_cache data = default_cache.get(CACHE_KEY, 'nada') if data == 'nada': data = self.read_db() default_cache.set(CACHE_KEY, data) return data def read_db(self): from .models import CacheVersion data = {} for cache_version in CacheVersion.objects.iterator(): data[cache_version.cache] = cache_version.version return data def get_cache_version(self, cache): try: return self.cache[cache] except KeyError: raise ValueError('Cache "%s" is not registered' % cache) def is_cache_valid(self, cache, version): try: return self.cache[cache] == version except KeyError: raise ValueError('Cache "%s" is not registered' % cache) def invalidate_cache(self, cache): from .cache import cache as default_cache from .models import CacheVersion self.cache[cache] += 1 CacheVersion.objects.filter(cache=cache).update(version=F('version') + 1) default_cache.delete(CACHE_KEY) def invalidate_all(self): from .cache import cache as default_cache from .models import CacheVersion CacheVersion.objects.update(version=F('version') + 1) default_cache.delete(CACHE_KEY) _controller = CacheBusterController() # Expose controller API def register(cache_name): _controller.register_cache(cache_name) def unregister(cache_name): _controller.unregister_cache(cache_name) def get_version(cache_name): return _controller.get_cache_version(cache_name) def is_valid(cache_name, version): return _controller.is_cache_valid(cache_name, version) def invalidate(cache_name): _controller.invalidate_cache(cache_name) def invalidate_all(): _controller.invalidate_all()