[ka6] snapshot pré-mission derumarketcatering
1 changed file +19 −2
modified
jobka/connectors/workday.py
+19 −2
@@ -5,7 +5,7 @@ | |||||
| 5 | # Fichier : jobka/connectors/workday.py | 5 | # Fichier : jobka/connectors/workday.py | ||
| 6 | # Rôle : Classe de plateforme Workday (API JSON publique wday/cxs) — un | 6 | # Rôle : Classe de plateforme Workday (API JSON publique wday/cxs) — un | ||
| 7 | # employeur = une sous-classe de ~10 lignes (TENANT, HOST, SITE) | 7 | # employeur = une sous-classe de ~10 lignes (TENANT, HOST, SITE) | ||
| 8 | −# Créé : 2026-08-17 Modifié : 2026-08-31 | 8 | +# Créé : 2026-08-17 Modifié : 2026-09-04 | ||
| 9 | # ============================================================================= | 9 | # ============================================================================= | ||
| 10 | """Plateforme Workday. | 10 | """Plateforme Workday. | ||
| 11 | 11 | ||||
@@ -30,11 +30,18 @@ import os | |||||
| 30 | import re | 30 | import re | ||
| 31 | import time | 31 | import time | ||
| 32 | 32 | ||||
| 33 | +import requests | ||||
| 34 | + | ||||
| 33 | from ..schema import JobPosting, clean_html, is_quebec_location | 35 | from ..schema import JobPosting, clean_html, is_quebec_location | ||
| 34 | from .base import BaseConnector | 36 | from .base import BaseConnector | ||
| 35 | 37 | ||||
| 36 | PAGE_SIZE = 20 | 38 | PAGE_SIZE = 20 | ||
| 37 | MAX_DETAILS = int(os.environ.get("JOBKA_WORKDAY_DETAIL_LIMIT", "300")) | 39 | MAX_DETAILS = int(os.environ.get("JOBKA_WORKDAY_DETAIL_LIMIT", "300")) | ||
| 40 | +# Échecs de pages détail tolérés par sync : une erreur passagère sur UNE page | ||||
| 41 | +# (504 Gateway Timeout constaté le 2026-09-04 sur walmart, ~1090 offres | ||||
| 42 | +# perdues pour un seul GET) ne doit pas avorter toute la source ; au-delà du | ||||
| 43 | +# budget, la panne est réelle et on la remonte dans sync_log. | ||||
| 44 | +DETAIL_MISS_BUDGET = 8 | ||||
| 38 | 45 | ||||
| 39 | 46 | ||||
| 40 | class WorkdayConnector(BaseConnector): | 47 | class WorkdayConnector(BaseConnector): | ||
@@ -207,6 +214,7 @@ class WorkdayConnector(BaseConnector): | |||||
| 207 | out: list[JobPosting] = [] | 214 | out: list[JobPosting] = [] | ||
| 208 | by_path: dict[str, JobPosting] = {} | 215 | by_path: dict[str, JobPosting] = {} | ||
| 209 | details_used = 0 | 216 | details_used = 0 | ||
| 217 | + detail_misses = 0 | ||||
| 210 | self._server_filtered = False | 218 | self._server_filtered = False | ||
| 211 | self._first_facets: list = [] | 219 | self._first_facets: list = [] | ||
| 212 | self._qc_facet = None | 220 | self._qc_facet = None | ||
@@ -238,7 +246,16 @@ class WorkdayConnector(BaseConnector): | |||||
| 238 | fresh[0] = True | 246 | fresh[0] = True | ||
| 239 | return self._fetch_detail(p) | 247 | return self._fetch_detail(p) | ||
| 240 | 248 | ||||
| 241 | − d = self.detail(str(eid), key, _fn) | 249 | + # page détail en erreur (5xx passager, coupure, non-JSON) : | ||
| 250 | + # repli sur le cache périmé et on continue — l'échec n'étant | ||||
| 251 | + # pas mis en cache, la page sera re-tentée au prochain cycle | ||||
| 252 | + try: | ||||
| 253 | + d = self.detail(str(eid), key, _fn) | ||||
| 254 | + except (requests.RequestException, RuntimeError): | ||||
| 255 | + detail_misses += 1 | ||||
| 256 | + if detail_misses > DETAIL_MISS_BUDGET: | ||||
| 257 | + raise | ||||
| 258 | + d = self.stale_detail(str(eid)) | ||||
| 242 | if fresh[0]: | 259 | if fresh[0]: | ||
| 243 | details_used += 1 | 260 | details_used += 1 | ||
| 244 | else: | 261 | else: | ||
| 245 | 262 | ||||