fix(backend): fiabilise le tri des lectures/predictions et la detection de redemarrage a zero
Backend / Tests exigeant une base (push) Failing after 38s
Backend / Lint, typage et tests (push) Successful in 1m29s
Backend / Audit des dépendances (push) Successful in 1m3s
SonarQube / build-back (push) Successful in 1m8s
SonarQube / build-front (push) Successful in 9m36s
SonarQube / test-back (push) Failing after 1m5s
SonarQube / test-front (push) Failing after 5m15s
SonarQube / SonarQube (push) Skipped
Backend / Tests exigeant une base (push) Failing after 38s
Backend / Lint, typage et tests (push) Successful in 1m29s
Backend / Audit des dépendances (push) Successful in 1m3s
SonarQube / build-back (push) Successful in 1m8s
SonarQube / build-front (push) Successful in 9m36s
SonarQube / test-back (push) Failing after 1m5s
SonarQube / test-front (push) Failing after 5m15s
SonarQube / SonarQube (push) Skipped
This commit is contained in:
@@ -16,10 +16,16 @@ class PredictionRepository:
|
||||
) -> Sequence[Prediction]:
|
||||
# Restreint à `available` : une prévision `insufficient_data`/`error` n'a pas de
|
||||
# `predicted_value` à comparer à une lecture réelle (détection d'anomalie).
|
||||
# Piège : `prediction` n'a pas d'unicité sur `(site_id, target_at)` (cf.
|
||||
# `enervision_ml.score`, qui insère toujours une nouvelle ligne plutôt que d'écraser la
|
||||
# précédente). `prediction_id` en dernier départage donc les égalités de `target_at` par
|
||||
# ordre croissant : `_detect_anomaly` construit un dict qui garde le dernier rencontré,
|
||||
# c'est-à-dire le run le plus récent plutôt qu'une ligne choisie au hasard par le plan
|
||||
# d'exécution.
|
||||
requete = (
|
||||
select(Prediction)
|
||||
.where(Prediction.target_at >= since, Prediction.status == "available")
|
||||
.order_by(Prediction.site_id, Prediction.target_at)
|
||||
.order_by(Prediction.site_id, Prediction.target_at, Prediction.prediction_id)
|
||||
)
|
||||
if site_id is not None:
|
||||
requete = requete.where(Prediction.site_id == site_id)
|
||||
|
||||
@@ -37,10 +37,13 @@ class ReadingRepository:
|
||||
async def list_since(self, *, since: datetime, site_id: str | None = None) -> Sequence[Reading]:
|
||||
# Trié par site puis par heure croissante : la détection d'alertes (spike) a besoin de
|
||||
# comparer chaque lecture à celle qui la précède immédiatement pour le même site.
|
||||
# `reading_id` en dernier départage : `uq_reading_source` autorise deux lignes au même
|
||||
# `site_id`+`timestamp` quand la `source` diffère (même piège que `latest_for_site`), sans
|
||||
# quoi l'ordre entre elles ne serait pas garanti d'un appel à l'autre.
|
||||
requete = (
|
||||
select(Reading)
|
||||
.where(Reading.timestamp >= since)
|
||||
.order_by(Reading.site_id, Reading.timestamp)
|
||||
.order_by(Reading.site_id, Reading.timestamp, Reading.reading_id)
|
||||
)
|
||||
if site_id is not None:
|
||||
requete = requete.where(Reading.site_id == site_id)
|
||||
|
||||
Reference in New Issue
Block a user