[ka6] fix connecteur firststudent: retry avec backoff sur 5xx transitoire dans la plateforme workday — un 500 isolé de l'API CXS (constaté 2026-09-07 18h18 sur firststudent.wd1, reparti seul) faisait échouer tout le sync car raise_for_status dans base.get/post court-circuitait le retry de _req_json (qui ne couvrait que le cas 200 non-JSON); les 4xx restent des échecs immédiats; sync rejoué: 35 offres (médiane 35.0)
1 changed file +17 −3
modified
jobka/connectors/workday.py
+17 −3
@@ -5,7 +5,7 @@ | ||
| 5 | 5 | # Fichier : jobka/connectors/workday.py |
| 6 | 6 | # Rôle : Classe de plateforme Workday (API JSON publique wday/cxs) — un |
| 7 | 7 | # employeur = une sous-classe de ~10 lignes (TENANT, HOST, SITE) |
| 8 | −# Créé : 2026-08-17 Modifié : 2026-09-04 | |
| 8 | +# Créé : 2026-08-17 Modifié : 2026-09-07 | |
| 9 | 9 | # ============================================================================= |
| 10 | 10 | """Plateforme Workday. |
| 11 | 11 | |
@@ -68,14 +68,28 @@ class WorkdayConnector(BaseConnector): | ||
| 68 | 68 | # sur de nombreux tenants) : on retente avec backoff avant |
| 69 | 69 | # d'abandonner, et l'erreur finale nomme le statut HTTP + |
| 70 | 70 | # content-type pour que sync_log soit diagnostiquable. |
| 71 | − last: ValueError | None = None | |
| 71 | + # Même traitement pour les 5xx transitoires (500 isolé constaté le | |
| 72 | + # 2026-09-07 sur firststudent.wd1, reparti seul) : raise_for_status | |
| 73 | + # dans base.get/post court-circuitait le retry et un seul 500 faisait | |
| 74 | + # échouer tout le sync. | |
| 75 | + last: Exception | None = None | |
| 76 | + resp = None | |
| 72 | 77 | for attempt in range(3): |
| 73 | − resp = (self.post if method == "post" else self.get)(url, **kwargs) | |
| 78 | + try: | |
| 79 | + resp = (self.post if method == "post" else self.get)(url, **kwargs) | |
| 80 | + except requests.HTTPError as exc: | |
| 81 | + if exc.response is None or exc.response.status_code < 500: | |
| 82 | + raise | |
| 83 | + last = exc | |
| 84 | + time.sleep(10 * (attempt + 1)) | |
| 85 | + continue | |
| 74 | 86 | try: |
| 75 | 87 | return resp.json() |
| 76 | 88 | except ValueError as exc: |
| 77 | 89 | last = exc |
| 78 | 90 | time.sleep(10 * (attempt + 1)) |
| 91 | + if resp is None: | |
| 92 | + raise RuntimeError(f"Workday 5xx après 3 essais : {last}") | |
| 79 | 93 | raise RuntimeError( |
| 80 | 94 | f"Workday non-JSON après 3 essais (HTTP {resp.status_code}, " |
| 81 | 95 | f"{resp.headers.get('content-type')}) : {last}") |
| 82 | 96 | |