From 0d290b9184a554cda7f6dc28d82401bb85cad7b3 Mon Sep 17 00:00:00 2001 From: Ivan Kolodyazhny Date: Tue, 21 Apr 2020 18:36:35 +0300 Subject: [PATCH] Fix django-compress caching issues django-compress doesn't work well with cache. If horizon is deployed in a containarized environment with pre-built static in images, django-compress tries to load old templates from cache. This patch introduces following changes: * update_angular_template_hash uses the correct Django cache backend now * fixed cache cleanup for memcached backend * added clean_angular_template_cache management command to clean cache manually without executing heavy 'compress' command. Closes-Bug: #1874657 Change-Id: If1fd61fa2e4b36e22797b0f54ac067a2a937f369 --- horizon/cache.py | 33 +++++++++++++++++++ horizon/templatetags/angular.py | 19 ++--------- .../cleanup_angular_template_cache.py | 24 ++++++++++++++ ...leanup-cache-command-64a5020755c5e05c.yaml | 10 ++++++ 4 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 horizon/cache.py create mode 100644 openstack_dashboard/management/commands/cleanup_angular_template_cache.py create mode 100644 releasenotes/notes/cleanup-cache-command-64a5020755c5e05c.yaml diff --git a/horizon/cache.py b/horizon/cache.py new file mode 100644 index 0000000000..a2e89c7693 --- /dev/null +++ b/horizon/cache.py @@ -0,0 +1,33 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from django.conf import settings +from django.core.cache import caches +from django.core.cache.utils import make_template_fragment_key + + +def cleanup_angular_template_cache(theme): + # The compressor has modified the angular template cache preloads + # which are cached in the 'COMPRESS_CACHE_BACKEND' Django cache. + django_cache = caches[settings.COMPRESS_CACHE_BACKEND] + + # generate the same key as used in _scripts.html when caching the + # preloads + key = make_template_fragment_key( + "angular", + ['template_cache_preloads', theme] + ) + + # if template preloads have been cached, clear them + if django_cache.get(key): + # Set to None because memcached doesn't remove records immediately + django_cache.set(key, None) diff --git a/horizon/templatetags/angular.py b/horizon/templatetags/angular.py index 6055adab19..857806cc06 100644 --- a/horizon/templatetags/angular.py +++ b/horizon/templatetags/angular.py @@ -15,11 +15,11 @@ from compressor.signals import post_compress from django.contrib.staticfiles import finders -from django.core.cache import caches -from django.core.cache.utils import make_template_fragment_key from django.dispatch import receiver from django import template +from horizon import cache + register = template.Library() @@ -37,21 +37,8 @@ def update_angular_template_hash(sender, **kwargs): compressed = context['compressed'] # the compressed content compressed_name = compressed['name'] # name of the compressed content if compressed_name == 'angular_template_cache_preloads': - # The compressor has modified the angular template cache preloads - # which are cached in the 'default' Django cache. Fetch that cache. - cache = caches['default'] - - # generate the same key as used in _scripts.html when caching the - # preloads theme = context['THEME'] # current theme being compressed - key = make_template_fragment_key( - "angular", - ['template_cache_preloads', theme] - ) - - # if template preloads have been cached, clear them - if cache.get(key): - cache.delete(key) + cache.cleanup_angular_template_cache(theme) @register.filter(name='angular_escapes') diff --git a/openstack_dashboard/management/commands/cleanup_angular_template_cache.py b/openstack_dashboard/management/commands/cleanup_angular_template_cache.py new file mode 100644 index 0000000000..8b7b9dbbd9 --- /dev/null +++ b/openstack_dashboard/management/commands/cleanup_angular_template_cache.py @@ -0,0 +1,24 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import settings +from django.core.management.base import BaseCommand + +from horizon import cache + + +class Command(BaseCommand): + help = 'Clears template cache for angularized views.' + + def handle(self, *args, **options): + for theme in settings.AVAILABLE_THEMES: + cache.cleanup_angular_template_cache(theme[0]) diff --git a/releasenotes/notes/cleanup-cache-command-64a5020755c5e05c.yaml b/releasenotes/notes/cleanup-cache-command-64a5020755c5e05c.yaml new file mode 100644 index 0000000000..a29d235148 --- /dev/null +++ b/releasenotes/notes/cleanup-cache-command-64a5020755c5e05c.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Added an ``cleanup_angular_template_cache`` management command, that clears + template cache for angularized views. The command is available + as ``./manage.py cleanup_angular_template_cache``. +fixes: + - | + [`bug/1874657 `_] Horizon + container upgrade works without additional ``./manage.py compress`` call.