pause idel
This commit is contained in:
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
|||||||
BATCH_SIZE = 1000
|
BATCH_SIZE = 250
|
||||||
@ -15,6 +15,32 @@ def run_once():
|
|||||||
log_info("[INFO] Aucune course active.")
|
log_info("[INFO] Aucune course active.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Appliquer les PAUSE_REQUEST avant tout traitement
|
||||||
|
# -------------------------------------------------
|
||||||
|
active_courses = get_active_con_ids(cur)
|
||||||
|
|
||||||
|
for con_id in active_courses:
|
||||||
|
|
||||||
|
engine_table = f"resultv2_{con_id}_lecture"
|
||||||
|
|
||||||
|
# Lire le statut actuel
|
||||||
|
cur.execute(f"SELECT process_status FROM `{engine_table}` LIMIT 1")
|
||||||
|
row = cur.fetchone()
|
||||||
|
|
||||||
|
if not row:
|
||||||
|
continue
|
||||||
|
|
||||||
|
status = (row["process_status"] or "").upper()
|
||||||
|
|
||||||
|
# Si CI4 a demandé une pause → Python applique la pause maintenant
|
||||||
|
if status == "PAUSE_REQUEST":
|
||||||
|
cur.execute(f"UPDATE `{engine_table}` SET process_status = 'PAUSE'")
|
||||||
|
cnx.commit()
|
||||||
|
log_info(f"[PAUSE APPLIED] con_id={con_id}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for con_id in con_ids:
|
for con_id in con_ids:
|
||||||
process_course(cur, cnx, con_id)
|
process_course(cur, cnx, con_id)
|
||||||
|
|
||||||
@ -30,4 +56,21 @@ def run_once():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
run_once()
|
import time
|
||||||
|
import msvcrt # Spécifique Windows
|
||||||
|
|
||||||
|
log_info("[TEST MODE] Boucle continue — appuyer ENTER pour arrêter.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
run_once()
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
if msvcrt.kbhit(): # Une touche a été pressée
|
||||||
|
key = msvcrt.getch()
|
||||||
|
if key == b'\r': # ENTER = arrêt
|
||||||
|
log_info("[TEST MODE] Arrêt demandé via ENTER.")
|
||||||
|
break
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
log_info("[TEST MODE] Arrêt via CTRL+C.")
|
||||||
|
|||||||
Binary file not shown.
BIN
engine/engine_components/__pycache__/regles.cpython-313.pyc
Normal file
BIN
engine/engine_components/__pycache__/regles.cpython-313.pyc
Normal file
Binary file not shown.
@ -9,6 +9,7 @@ from datetime import datetime, timezone
|
|||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from engine.utils import format_temps_decimal
|
from engine.utils import format_temps_decimal
|
||||||
|
from engine.engine_components.regles import resolve_priority
|
||||||
|
|
||||||
LOCAL_TZ = ZoneInfo("America/Toronto")
|
LOCAL_TZ = ZoneInfo("America/Toronto")
|
||||||
|
|
||||||
@ -59,6 +60,30 @@ def process_course(cur, cnx, con_id: int):
|
|||||||
engine_table = f"resultv2_{con_id}_lecture"
|
engine_table = f"resultv2_{con_id}_lecture"
|
||||||
classement_table = f"resultv2_{con_id}_classement"
|
classement_table = f"resultv2_{con_id}_classement"
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Pause
|
||||||
|
# -------------------------------------------------
|
||||||
|
|
||||||
|
# Lire le statut
|
||||||
|
cur.execute(f"SELECT process_status FROM `{engine_table}` LIMIT 1")
|
||||||
|
row = cur.fetchone()
|
||||||
|
status = (row["process_status"] or "").upper()
|
||||||
|
|
||||||
|
# Si une pause est demandée
|
||||||
|
if status == "PAUSE_REQUEST":
|
||||||
|
# Le moteur se met officiellement en PAUSE
|
||||||
|
cur.execute(f"UPDATE `{engine_table}` SET process_status = 'PAUSE'")
|
||||||
|
cnx.commit()
|
||||||
|
log_info(f"[PAUSE] con_id={con_id} — pause appliquée avant traitement.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Si déjà en pause → sortir immédiatement
|
||||||
|
if status == "PAUSE":
|
||||||
|
log_info(f"[PAUSE] con_id={con_id} — course déjà en pause.")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Lire dernier ID traité (mécanisme incremental)
|
# Lire dernier ID traité (mécanisme incremental)
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
@ -84,6 +109,8 @@ def process_course(cur, cnx, con_id: int):
|
|||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
for lec in lectures:
|
for lec in lectures:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rcourse_id = int(lec["rcourse_id"])
|
rcourse_id = int(lec["rcourse_id"])
|
||||||
chr_loc = lec["chrinfo_location"]
|
chr_loc = lec["chrinfo_location"]
|
||||||
timestamp = Decimal(lec["chrinfo_time"])
|
timestamp = Decimal(lec["chrinfo_time"])
|
||||||
@ -249,94 +276,4 @@ def compute_tour(cur, detail_table, tp_id, dossard):
|
|||||||
return last_tour + 1, prev_ts
|
return last_tour + 1, prev_ts
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Règle de priorité : remplace, rejette, ou force tour
|
|
||||||
# -------------------------------------------------
|
|
||||||
def resolve_priority(
|
|
||||||
cur,
|
|
||||||
cnx,
|
|
||||||
detail_table,
|
|
||||||
tp_id,
|
|
||||||
dossard,
|
|
||||||
new_timestamp,
|
|
||||||
new_priority,
|
|
||||||
det_id,
|
|
||||||
tp_config
|
|
||||||
):
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Lecture de la fenêtre backup pour priorité
|
|
||||||
# -------------------------------------------------
|
|
||||||
cfg = (
|
|
||||||
tp_config[tp_id]["config"]
|
|
||||||
.get("config_tp", {})
|
|
||||||
.get("clef_temp_bbk", [])
|
|
||||||
)
|
|
||||||
|
|
||||||
backup_window = 0
|
|
||||||
if cfg:
|
|
||||||
try:
|
|
||||||
backup_window = int(cfg[0]["value1"])
|
|
||||||
except:
|
|
||||||
backup_window = 0
|
|
||||||
|
|
||||||
log_debug(f"[resolve_priority] backup_window={backup_window}")
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Si backup_window = 0 → toujours accepter
|
|
||||||
# -------------------------------------------------
|
|
||||||
if backup_window <= 0:
|
|
||||||
return 1, None, None, None
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Recherche d'une lecture existante dans la fenêtre
|
|
||||||
# -------------------------------------------------
|
|
||||||
cur.execute(f"""
|
|
||||||
SELECT detail_id, controller_priority, timestamp_read, tour
|
|
||||||
FROM `{detail_table}`
|
|
||||||
WHERE tp_id = %s
|
|
||||||
AND cla_info_dossard = %s
|
|
||||||
AND status = 1
|
|
||||||
AND ABS(timestamp_read - %s) <= %s
|
|
||||||
LIMIT 1
|
|
||||||
""", (tp_id, dossard, str(new_timestamp), backup_window))
|
|
||||||
|
|
||||||
row = cur.fetchone()
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Aucun doublon → accepter
|
|
||||||
# -------------------------------------------------
|
|
||||||
if not row:
|
|
||||||
return 1, None, None, None
|
|
||||||
|
|
||||||
old_id = row["detail_id"]
|
|
||||||
old_priority = row["controller_priority"]
|
|
||||||
old_tour = row["tour"]
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
|
||||||
# Comparaison des priorités
|
|
||||||
# -------------------------------------------------
|
|
||||||
|
|
||||||
# Nouvelle lecture moins prioritaire → rejet
|
|
||||||
if new_priority > old_priority:
|
|
||||||
return 0, "LOWER_PRIORITY", det_id, None
|
|
||||||
|
|
||||||
# Nouvelle lecture plus prioritaire → remplacer
|
|
||||||
if new_priority < old_priority:
|
|
||||||
|
|
||||||
cur.execute(f"""
|
|
||||||
UPDATE `{detail_table}`
|
|
||||||
SET
|
|
||||||
status = 0,
|
|
||||||
reason_code = 'REPLACED_BY_HIGHER_PRIORITY',
|
|
||||||
reason_ref_id = %s
|
|
||||||
WHERE detail_id = %s
|
|
||||||
""", (det_id, old_id))
|
|
||||||
|
|
||||||
cnx.commit()
|
|
||||||
|
|
||||||
forced_tour = old_tour
|
|
||||||
return 1, None, None, forced_tour
|
|
||||||
|
|
||||||
# Même priorité → rejet
|
|
||||||
return 0, "EQUAL_PRIORITY", det_id, None
|
|
||||||
93
engine/engine_components/regles.py
Normal file
93
engine/engine_components/regles.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# regles.py
|
||||||
|
from engine.logger import log_info, log_debug
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Règle de priorité : remplace, rejette, ou force tour
|
||||||
|
# -------------------------------------------------
|
||||||
|
def resolve_priority(
|
||||||
|
cur,
|
||||||
|
cnx,
|
||||||
|
detail_table,
|
||||||
|
tp_id,
|
||||||
|
dossard,
|
||||||
|
new_timestamp,
|
||||||
|
new_priority,
|
||||||
|
det_id,
|
||||||
|
tp_config
|
||||||
|
):
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Lecture de la fenêtre backup pour priorité
|
||||||
|
# -------------------------------------------------
|
||||||
|
cfg = (
|
||||||
|
tp_config[tp_id]["config"]
|
||||||
|
.get("config_tp", {})
|
||||||
|
.get("clef_temp_bbk", [])
|
||||||
|
)
|
||||||
|
|
||||||
|
backup_window = 0
|
||||||
|
if cfg:
|
||||||
|
try:
|
||||||
|
backup_window = int(cfg[0]["value1"])
|
||||||
|
except:
|
||||||
|
backup_window = 0
|
||||||
|
|
||||||
|
log_debug(f"[resolve_priority] backup_window={backup_window}")
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Si backup_window = 0 → toujours accepter
|
||||||
|
# -------------------------------------------------
|
||||||
|
if backup_window <= 0:
|
||||||
|
return 1, None, None, None
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Recherche d'une lecture existante dans la fenêtre
|
||||||
|
# -------------------------------------------------
|
||||||
|
cur.execute(f"""
|
||||||
|
SELECT detail_id, controller_priority, timestamp_read, tour
|
||||||
|
FROM `{detail_table}`
|
||||||
|
WHERE tp_id = %s
|
||||||
|
AND cla_info_dossard = %s
|
||||||
|
AND status = 1
|
||||||
|
AND ABS(timestamp_read - %s) <= %s
|
||||||
|
LIMIT 1
|
||||||
|
""", (tp_id, dossard, str(new_timestamp), backup_window))
|
||||||
|
|
||||||
|
row = cur.fetchone()
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Aucun doublon → accepter
|
||||||
|
# -------------------------------------------------
|
||||||
|
if not row:
|
||||||
|
return 1, None, None, None
|
||||||
|
|
||||||
|
old_id = row["detail_id"]
|
||||||
|
old_priority = row["controller_priority"]
|
||||||
|
old_tour = row["tour"]
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Comparaison des priorités
|
||||||
|
# -------------------------------------------------
|
||||||
|
|
||||||
|
# Nouvelle lecture moins prioritaire → rejet
|
||||||
|
if new_priority > old_priority:
|
||||||
|
return 0, "LOWER_PRIORITY", det_id, None
|
||||||
|
|
||||||
|
# Nouvelle lecture plus prioritaire → remplacer
|
||||||
|
if new_priority < old_priority:
|
||||||
|
|
||||||
|
cur.execute(f"""
|
||||||
|
UPDATE `{detail_table}`
|
||||||
|
SET
|
||||||
|
status = 0,
|
||||||
|
reason_code = 'REPLACED_BY_HIGHER_PRIORITY',
|
||||||
|
reason_ref_id = %s
|
||||||
|
WHERE detail_id = %s
|
||||||
|
""", (det_id, old_id))
|
||||||
|
|
||||||
|
cnx.commit()
|
||||||
|
|
||||||
|
forced_tour = old_tour
|
||||||
|
return 1, None, None, forced_tour
|
||||||
|
|
||||||
|
# Même priorité → rejet
|
||||||
|
return 0, "EQUAL_PRIORITY", det_id, None
|
||||||
Reference in New Issue
Block a user