From 0634dbd0aa1fab8499e4aeb69f61f53300ed22b0 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Mon, 15 Jan 2024 17:49:28 +0100
Subject: [PATCH] Cache: delete_pattern

---
 app/scodoc/sco_cache.py   | 27 +++++++++++++++++++++++++++
 sco_version.py            |  2 +-
 tests/unit/test_caches.py |  4 ++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/app/scodoc/sco_cache.py b/app/scodoc/sco_cache.py
index 4c9960dfd..e31b6a18d 100644
--- a/app/scodoc/sco_cache.py
+++ b/app/scodoc/sco_cache.py
@@ -121,6 +121,33 @@ class ScoDocCache:
         for oid in oids:
             cls.delete(oid)
 
+    @classmethod
+    def delete_pattern(cls, pattern: str, std_prefix=True) -> int:
+        """Delete all keys matching pattern.
+        The pattern starts with flask_cache_<dept_acronym>.
+        If std_prefix is true (default), the prefix is added
+        to the given pattern.
+        Examples:
+        'TABASSI_tableau-etud-1234:*'
+        Or, with std_prefix false, 'flask_cache_RT_TABASSI_tableau-etud-1234:*'
+
+        Returns number of keys deleted.
+        """
+        # see https://stackoverflow.com/questions/36708461/flask-cache-list-keys-based-on-a-pattern
+        assert CACHE.cache.__class__.__name__ == "RedisCache"  # Redis specific
+        import redis
+
+        if std_prefix:
+            pattern = "flask_cache_" + g.scodoc_dept + "_" + cls.prefix + "_" + pattern
+
+        r = redis.Redis()
+        count = 0
+        for key in r.scan_iter(pattern):
+            log(f"{cls.__name__}.delete_pattern({key})")
+            r.delete(key)
+            count += 1
+        return count
+
 
 class EvaluationCache(ScoDocCache):
     """Cache for evaluations.
diff --git a/sco_version.py b/sco_version.py
index 53da13f95..7b986ac6c 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,7 @@
 # -*- mode: python -*-
 # -*- coding: utf-8 -*-
 
-SCOVERSION = "9.6.77"
+SCOVERSION = "9.6.78"
 
 SCONAME = "ScoDoc"
 
diff --git a/tests/unit/test_caches.py b/tests/unit/test_caches.py
index 3a4882d77..0e3766ba0 100644
--- a/tests/unit/test_caches.py
+++ b/tests/unit/test_caches.py
@@ -48,6 +48,10 @@ def test_notes_table(test_client):  # XXX A REVOIR POUR TESTER RES TODO
         formsemestre_id = sem["formsemestre_id"]
         nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
         assert sco_cache.ResultatsSemestreCache.get(formsemestre_id)
+    # Efface les semestres
+    sco_cache.ResultatsSemestreCache.delete_pattern("*")
+    for sem in sems[:10]:
+        assert sco_cache.ResultatsSemestreCache.get(formsemestre_id) is None
 
 
 def test_cache_evaluations(test_client):
-- 
GitLab