Fix "Da Nang": invalidation caches poids evals sur modifs UEs

This commit is contained in:
Emmanuel Viennet 2022-06-24 03:34:52 +02:00
parent f546837821
commit 3e5ae5d961
4 changed files with 30 additions and 19 deletions

View File

@ -6,6 +6,7 @@ from app import db
from app.comp import df_cache from app.comp import df_cache
from app.models import SHORT_STR_LEN from app.models import SHORT_STR_LEN
from app.models.modules import Module from app.models.modules import Module
from app.models.moduleimpls import ModuleImpl
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
@ -97,6 +98,13 @@ class Formation(db.Model):
else: else:
keys = f"{self.id}.{semestre_idx}" keys = f"{self.id}.{semestre_idx}"
df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"}) df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"})
# Invalidate aussi les poids de toutes les évals de la formation
for modimpl in ModuleImpl.query.filter(
ModuleImpl.module_id == Module.id,
Module.formation_id == self.id,
):
modimpl.invalidate_evaluations_poids()
sco_cache.invalidate_formsemestre() sco_cache.invalidate_formsemestre()
def invalidate_cached_sems(self): def invalidate_cached_sems(self):

View File

@ -67,6 +67,7 @@ class ScoDocCache:
timeout = None # ttl, infinite by default timeout = None # ttl, infinite by default
prefix = "" prefix = ""
verbose = False # if true, verbose logging (debug)
@classmethod @classmethod
def _get_key(cls, oid): def _get_key(cls, oid):
@ -87,7 +88,10 @@ class ScoDocCache:
def set(cls, oid, value): def set(cls, oid, value):
"""Store value""" """Store value"""
key = cls._get_key(oid) key = cls._get_key(oid)
# log(f"CACHE key={key}, type={type(value)}, timeout={cls.timeout}") if cls.verbose:
log(
f"{cls.__name__}.set key={key}, type={type(value).__name__}, timeout={cls.timeout}"
)
try: try:
status = CACHE.set(key, value, timeout=cls.timeout) status = CACHE.set(key, value, timeout=cls.timeout)
if not status: if not status:
@ -101,11 +105,15 @@ class ScoDocCache:
@classmethod @classmethod
def delete(cls, oid): def delete(cls, oid):
"""Remove from cache""" """Remove from cache"""
# if cls.verbose:
# log(f"{cls.__name__}.delete({oid})")
CACHE.delete(cls._get_key(oid)) CACHE.delete(cls._get_key(oid))
@classmethod @classmethod
def delete_many(cls, oids): def delete_many(cls, oids):
"""Remove multiple keys at once""" """Remove multiple keys at once"""
if cls.verbose:
log(f"{cls.__name__}.delete_many({oids})")
# delete_many seems bugged: # delete_many seems bugged:
# CACHE.delete_many([cls._get_key(oid) for oid in oids]) # CACHE.delete_many([cls._get_key(oid) for oid in oids])
for oid in oids: for oid in oids:

View File

@ -121,12 +121,7 @@ def do_ue_create(args):
# create # create
ue_id = _ueEditor.create(cnx, args) ue_id = _ueEditor.create(cnx, args)
# Invalidate cache: vire les poids de toutes les évals de la formation formation: Formation = Formation.query.get(args["formation_id"])
for modimpl in ModuleImpl.query.filter(
ModuleImpl.module_id == Module.id, Module.formation_id == args["formation_id"]
):
modimpl.invalidate_evaluations_poids()
formation = Formation.query.get(args["formation_id"])
formation.invalidate_module_coefs() formation.invalidate_module_coefs()
# news # news
ue = UniteEns.query.get(ue_id) ue = UniteEns.query.get(ue_id)
@ -144,11 +139,10 @@ def do_ue_create(args):
def do_ue_delete(ue_id, delete_validations=False, force=False): def do_ue_delete(ue_id, delete_validations=False, force=False):
"delete UE and attached matieres (but not modules)" "delete UE and attached matieres (but not modules)"
from app.scodoc import sco_formations
from app.scodoc import sco_parcours_dut from app.scodoc import sco_parcours_dut
ue = UniteEns.query.get_or_404(ue_id) ue = UniteEns.query.get_or_404(ue_id)
formation_id = ue.formation_id formation = ue.formation
semestre_idx = ue.semestre_idx semestre_idx = ue.semestre_idx
if not ue.can_be_deleted(): if not ue.can_be_deleted():
raise ScoNonEmptyFormationObject( raise ScoNonEmptyFormationObject(
@ -157,7 +151,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False):
dest_url=url_for( dest_url=url_for(
"notes.ue_table", "notes.ue_table",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formation_id=formation_id, formation_id=formation.id,
semestre_idx=semestre_idx, semestre_idx=semestre_idx,
), ),
) )
@ -181,7 +175,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False):
cancel_url=url_for( cancel_url=url_for(
"notes.ue_table", "notes.ue_table",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formation_id=formation_id, formation_id=formation.id,
semestre_idx=semestre_idx, semestre_idx=semestre_idx,
), ),
parameters={"ue_id": ue.id, "dialog_confirmed": 1}, parameters={"ue_id": ue.id, "dialog_confirmed": 1},
@ -207,13 +201,13 @@ def do_ue_delete(ue_id, delete_validations=False, force=False):
_ueEditor.delete(cnx, ue.id) _ueEditor.delete(cnx, ue.id)
# > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement
# utilisé: acceptable de tout invalider): # utilisé: acceptable de tout invalider):
sco_cache.invalidate_formsemestre() formation.invalidate_module_coefs()
# -> invalide aussi .invalidate_formsemestre()
# news # news
F = sco_formations.formation_list(args={"formation_id": formation_id})[0]
ScolarNews.add( ScolarNews.add(
typ=ScolarNews.NEWS_FORM, typ=ScolarNews.NEWS_FORM,
obj=formation_id, obj=formation.id,
text=f"Modification de la formation {F['acronyme']}", text=f"Modification de la formation {formation.acronyme}",
max_frequency=10 * 60, max_frequency=10 * 60,
) )
# #
@ -222,7 +216,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False):
url_for( url_for(
"notes.ue_table", "notes.ue_table",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formation_id=formation_id, formation_id=formation.id,
semestre_idx=semestre_idx, semestre_idx=semestre_idx,
) )
) )
@ -1304,8 +1298,9 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
formation = Formation.query.get(ue["formation_id"]) formation = Formation.query.get(ue["formation_id"])
if not dont_invalidate_cache: if not dont_invalidate_cache:
# Invalide les semestres utilisant cette formation: # Invalide les semestres utilisant cette formation
formation.invalidate_cached_sems() # ainsi que les poids et coefs
formation.invalidate_module_coefs()
# essai edition en ligne: # essai edition en ligne:

View File

@ -192,7 +192,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
"""Tableau de bord module (liste des evaluations etc)""" """Tableau de bord module (liste des evaluations etc)"""
if not isinstance(moduleimpl_id, int): if not isinstance(moduleimpl_id, int):
raise ScoInvalidIdType("moduleimpl_id must be an integer !") raise ScoInvalidIdType("moduleimpl_id must be an integer !")
modimpl = ModuleImpl.query.get_or_404(moduleimpl_id) modimpl: ModuleImpl = ModuleImpl.query.get_or_404(moduleimpl_id)
M = modimpl.to_dict() M = modimpl.to_dict()
formsemestre_id = M["formsemestre_id"] formsemestre_id = M["formsemestre_id"]
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]