From 6122dcacc75163628a2544f6819d7623e93245d0 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sun, 21 Jun 2020 12:40:01 +0200 Subject: [PATCH] flows: fix flow cache not being cleared correctly when stages are saved --- passbook/flows/apps.py | 6 ++++++ passbook/flows/signals.py | 31 +++++++++++++++++++++++++++++++ passbook/policies/apps.py | 2 +- passbook/root/settings.py | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 passbook/flows/signals.py diff --git a/passbook/flows/apps.py b/passbook/flows/apps.py index 11f2d21d4..f31f699da 100644 --- a/passbook/flows/apps.py +++ b/passbook/flows/apps.py @@ -1,4 +1,6 @@ """passbook flows app config""" +from importlib import import_module + from django.apps import AppConfig @@ -9,3 +11,7 @@ class PassbookFlowsConfig(AppConfig): label = "passbook_flows" mountpoint = "flows/" verbose_name = "passbook Flows" + + def ready(self): + """Load policy cache clearing signals""" + import_module("passbook.flows.signals") diff --git a/passbook/flows/signals.py b/passbook/flows/signals.py new file mode 100644 index 000000000..d4353ef94 --- /dev/null +++ b/passbook/flows/signals.py @@ -0,0 +1,31 @@ +"""passbook flow signals""" +from django.core.cache import cache +from django.db.models.signals import post_save +from django.dispatch import receiver +from structlog import get_logger + +LOGGER = get_logger() + + +@receiver(post_save) +# pylint: disable=unused-argument +def invalidate_flow_cache(sender, instance, **_): + """Invalidate flow cache when flow is updated""" + from passbook.flows.models import Flow, FlowStageBinding, Stage + from passbook.flows.planner import cache_key + + if isinstance(instance, Flow): + LOGGER.debug("Invalidating Flow cache", flow=instance) + cache.delete(f"{cache_key(instance)}*") + if isinstance(instance, FlowStageBinding): + LOGGER.debug("Invalidating Flow cache from FlowStageBinding", binding=instance) + cache.delete(f"{cache_key(instance.flow)}*") + if isinstance(instance, Stage): + LOGGER.debug("Invalidating Flow cache from Stage", stage=instance) + total = 0 + for binding in FlowStageBinding.objects.filter(stage=instance): + prefix = cache_key(binding.flow) + keys = cache.keys(f"{prefix}*") + total += len(keys) + cache.delete_many(keys) + LOGGER.debug("Deleted keys", len=total) diff --git a/passbook/policies/apps.py b/passbook/policies/apps.py index 946f84609..f300fe6f3 100644 --- a/passbook/policies/apps.py +++ b/passbook/policies/apps.py @@ -12,5 +12,5 @@ class PassbookPoliciesConfig(AppConfig): verbose_name = "passbook Policies" def ready(self): - """Load source_types from config file""" + """Load policy cache clearing signals""" import_module("passbook.policies.signals") diff --git a/passbook/root/settings.py b/passbook/root/settings.py index 739edc462..43983c159 100644 --- a/passbook/root/settings.py +++ b/passbook/root/settings.py @@ -347,6 +347,7 @@ _LOGGING_HANDLER_MAP = { "passbook": LOG_LEVEL, "django": "WARNING", "celery": "WARNING", + "selenium": "WARNING", "grpc": LOG_LEVEL, "oauthlib": LOG_LEVEL, "oauth2_provider": LOG_LEVEL,