From 6f842dc8777b5caa87c43bf8bb4ebe2f715ae5ce Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 23 Jun 2022 17:53:27 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Fix:=20bug=20"rennes"=20sur=20les=20formsem?= =?UTF-8?q?estres=20sans=20formation=20associ=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_bulletins.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index df790649..daf4a941 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -158,9 +158,24 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"): I["server_name"] = request.url_root # Formation et parcours - I["formation"] = sco_formations.formation_list( - args={"formation_id": I["sem"]["formation_id"]} - )[0] + if I["sem"]["formation_id"]: + I["formation"] = sco_formations.formation_list( + args={"formation_id": I["sem"]["formation_id"]} + )[0] + else: # what's the fuck ? + I["formation"] = { + "acronyme": "?", + "code_specialite": "", + "dept_id": 1, + "formation_code": "?", + "formation_id": -1, + "id": -1, + "referentiel_competence_id": None, + "titre": "?", + "titre_officiel": "?", + "type_parcours": 0, + "version": 0, + } I["parcours"] = sco_codes_parcours.get_parcours_from_code( I["formation"]["type_parcours"] ) From f546837821f4f0e63a02871caebf2b7e0920a2f2 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 24 Jun 2022 03:32:48 +0200 Subject: [PATCH 2/3] Modif config log: moins verbeux, evite requetes ordinaires --- app/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/__init__.py b/app/__init__.py index a1862aaa..66c6effd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -205,6 +205,10 @@ def create_app(config_class=DevConfig): app = Flask(__name__, static_url_path="/ScoDoc/static", static_folder="static") app.wsgi_app = ReverseProxied(app.wsgi_app) app.logger.setLevel(logging.DEBUG) + + # Evite de logguer toutes les requetes dans notre log + logging.getLogger("werkzeug").disabled = True + app.config.from_object(config_class) db.init_app(app) From 3e5ae5d96138aac161ed58318ff2eb1c781ac97b Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 24 Jun 2022 03:34:52 +0200 Subject: [PATCH 3/3] Fix "Da Nang": invalidation caches poids evals sur modifs UEs --- app/models/formations.py | 8 ++++++++ app/scodoc/sco_cache.py | 10 +++++++++- app/scodoc/sco_edit_ue.py | 29 ++++++++++++----------------- app/scodoc/sco_moduleimpl_status.py | 2 +- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/app/models/formations.py b/app/models/formations.py index 43d3d680..84295711 100644 --- a/app/models/formations.py +++ b/app/models/formations.py @@ -6,6 +6,7 @@ from app import db from app.comp import df_cache from app.models import SHORT_STR_LEN from app.models.modules import Module +from app.models.moduleimpls import ModuleImpl from app.models.ues import UniteEns from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours @@ -97,6 +98,13 @@ class Formation(db.Model): else: keys = f"{self.id}.{semestre_idx}" 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() def invalidate_cached_sems(self): diff --git a/app/scodoc/sco_cache.py b/app/scodoc/sco_cache.py index 8fcc6f7e..7975e3b2 100644 --- a/app/scodoc/sco_cache.py +++ b/app/scodoc/sco_cache.py @@ -67,6 +67,7 @@ class ScoDocCache: timeout = None # ttl, infinite by default prefix = "" + verbose = False # if true, verbose logging (debug) @classmethod def _get_key(cls, oid): @@ -87,7 +88,10 @@ class ScoDocCache: def set(cls, oid, value): """Store value""" 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: status = CACHE.set(key, value, timeout=cls.timeout) if not status: @@ -101,11 +105,15 @@ class ScoDocCache: @classmethod def delete(cls, oid): """Remove from cache""" + # if cls.verbose: + # log(f"{cls.__name__}.delete({oid})") CACHE.delete(cls._get_key(oid)) @classmethod def delete_many(cls, oids): """Remove multiple keys at once""" + if cls.verbose: + log(f"{cls.__name__}.delete_many({oids})") # delete_many seems bugged: # CACHE.delete_many([cls._get_key(oid) for oid in oids]) for oid in oids: diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 33ffc69c..82dd77b1 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -121,12 +121,7 @@ def do_ue_create(args): # create ue_id = _ueEditor.create(cnx, args) - # Invalidate cache: vire les poids de toutes les évals de la formation - 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: Formation = Formation.query.get(args["formation_id"]) formation.invalidate_module_coefs() # news 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): "delete UE and attached matieres (but not modules)" - from app.scodoc import sco_formations from app.scodoc import sco_parcours_dut ue = UniteEns.query.get_or_404(ue_id) - formation_id = ue.formation_id + formation = ue.formation semestre_idx = ue.semestre_idx if not ue.can_be_deleted(): raise ScoNonEmptyFormationObject( @@ -157,7 +151,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False): dest_url=url_for( "notes.ue_table", scodoc_dept=g.scodoc_dept, - formation_id=formation_id, + formation_id=formation.id, semestre_idx=semestre_idx, ), ) @@ -181,7 +175,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False): cancel_url=url_for( "notes.ue_table", scodoc_dept=g.scodoc_dept, - formation_id=formation_id, + formation_id=formation.id, semestre_idx=semestre_idx, ), 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) # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement # utilisé: acceptable de tout invalider): - sco_cache.invalidate_formsemestre() + formation.invalidate_module_coefs() + # -> invalide aussi .invalidate_formsemestre() # news - F = sco_formations.formation_list(args={"formation_id": formation_id})[0] ScolarNews.add( typ=ScolarNews.NEWS_FORM, - obj=formation_id, - text=f"Modification de la formation {F['acronyme']}", + obj=formation.id, + text=f"Modification de la formation {formation.acronyme}", max_frequency=10 * 60, ) # @@ -222,7 +216,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False): url_for( "notes.ue_table", scodoc_dept=g.scodoc_dept, - formation_id=formation_id, + formation_id=formation.id, 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"]) if not dont_invalidate_cache: - # Invalide les semestres utilisant cette formation: - formation.invalidate_cached_sems() + # Invalide les semestres utilisant cette formation + # ainsi que les poids et coefs + formation.invalidate_module_coefs() # essai edition en ligne: diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index b9e6a3ee..59bcea3a 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -192,7 +192,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): """Tableau de bord module (liste des evaluations etc)""" if not isinstance(moduleimpl_id, int): 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() formsemestre_id = M["formsemestre_id"] Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]