SPB Git

spb/job-ka

Public

[ka6] fix connecteur bento_sushi: reprise sur réponses ADP 200 non-JSON (retry+backoff, erreur diagnosticable)

Simon-Pierre Boucher committed (Aug 30, 2026) parent 4dcbd45 Browse files

1 changed file +23 −6

Unified Split
modified jobka/connectors/adp.py +23 −6
@@ -5,7 +5,7 @@
5 # Fichier : jobka/connectors/adp.py 5 # Fichier : jobka/connectors/adp.py
6 # Rôle : Classe de plateforme ADP Workforce Now (centre de carrières) — 6 # Rôle : Classe de plateforme ADP Workforce Now (centre de carrières) —
7 # API JSON publique job-requisitions, un employeur = une sous-classe 7 # API JSON publique job-requisitions, un employeur = une sous-classe
8−# Créé : 2026-08-18 Modifié : 2026-08-25 8+# Créé : 2026-08-18 Modifié : 2026-08-30
9 # ============================================================================= 9 # =============================================================================
10 """Plateforme ADP Workforce Now (workforcenow.adp.com). 10 """Plateforme ADP Workforce Now (workforcenow.adp.com).
11 11
@@ -21,6 +21,7 @@ API JSON publique du centre de carrières :
21 from __future__ import annotations 21 from __future__ import annotations
22 22
23 import os 23 import os
24+import time
24 25
25 from ..schema import JobPosting, clean_html, is_quebec_location 26 from ..schema import JobPosting, clean_html, is_quebec_location
26 from .base import BaseConnector 27 from .base import BaseConnector
@@ -50,6 +51,24 @@ class ADPWorkforceNowConnector(BaseConnector):
50 FORCE_CITY = "" # employeurs mono-site QC dont le babillard n'expose 51 FORCE_CITY = "" # employeurs mono-site QC dont le babillard n'expose
51 # aucune requisitionLocation : ville imposée 52 # aucune requisitionLocation : ville imposée
52 53
54+ def _get_json(self, url: str, params: dict) -> dict:
55+ # ADP renvoie parfois 200 avec un corps vide/HTML (fenêtres de
56+ # maintenance nocturnes constatées les 29-30 août 2026) : on retente
57+ # avec backoff avant d'abandonner, et l'erreur finale nomme le statut
58+ # HTTP + content-type pour que sync_log soit diagnostiquable.
59+ last: ValueError | None = None
60+ for attempt in range(3):
61+ resp = self.get(url, params=params,
62+ headers={"Accept": "application/json"})
63+ try:
64+ return resp.json()
65+ except ValueError as exc:
66+ last = exc
67+ time.sleep(10 * (attempt + 1))
68+ raise RuntimeError(
69+ f"ADP non-JSON après 3 essais (HTTP {resp.status_code}, "
70+ f"{resp.headers.get('content-type')}) : {last}")
71+
53 def _params(self, extra: dict | None = None) -> dict: 72 def _params(self, extra: dict | None = None) -> dict:
54 p = {"cid": self.CID, "ccId": self.CCID, "lang": self.LANG, 73 p = {"cid": self.CID, "ccId": self.CCID, "lang": self.LANG,
55 "locale": self.LANG} 74 "locale": self.LANG}
@@ -81,8 +100,7 @@ class ADPWorkforceNowConnector(BaseConnector):
81 for l in locations) 100 for l in locations)
82 101
83 def _fetch_detail(self, item_id: str) -> dict: 102 def _fetch_detail(self, item_id: str) -> dict:
84− data = self.get(f"{_API}/{item_id}", params=self._params(), 103+ data = self._get_json(f"{_API}/{item_id}", params=self._params())
85− headers={"Accept": "application/json"}).json()
86 return {"description": clean_html( 104 return {"description": clean_html(
87 data.get("requisitionDescription") or "")} 105 data.get("requisitionDescription") or "")}
88 106
@@ -91,9 +109,8 @@ class ADPWorkforceNowConnector(BaseConnector):
91 details_used = 0 109 details_used = 0
92 skip = 0 110 skip = 0
93 for _ in range(self.max_pages): 111 for _ in range(self.max_pages):
94− data = self.get(_API, params=self._params( 112+ data = self._get_json(_API, params=self._params(
95− {"$top": str(PAGE_SIZE), "$skip": str(skip)}), 113+ {"$top": str(PAGE_SIZE), "$skip": str(skip)}))
96− headers={"Accept": "application/json"}).json()
97 reqs = data.get("jobRequisitions") or [] 114 reqs = data.get("jobRequisitions") or []
98 if not reqs and skip == 0 and self.LANG != "en_US": 115 if not reqs and skip == 0 and self.LANG != "en_US":
99 # certains centres de carrières ne répondent qu'en anglais 116 # certains centres de carrières ne répondent qu'en anglais
100 117
Menu

Theme