SPB Git

spb/job-ka

Public

[ka6] fix connecteur groupemaurice: 502 Bad Gateway transitoire du frontal Dayforce avortait tout le sync (stale 5,3 h, un seul POST search en échec). Garde-fou dans DayforceConnector: le POST de recherche retente une fois après pause sur 5xx, puis lève (sync en échec, jamais un faux 0) — même pattern que njoyn 33dba44 / digitalrecruiters 81cf8e2. Sync isolé re-testé: 108 offres trouvées (= médiane 108).

Simon-Pierre Boucher committed (Aug 27, 2026) parent f4038e4 Browse files

1 changed file +29 −7

Unified Split
modified jobka/connectors/dayforce.py +29 −7
@@ -5,7 +5,7 @@
5 # Fichier : jobka/connectors/dayforce.py 5 # Fichier : jobka/connectors/dayforce.py
6 # Rôle : Classe de plateforme Dayforce HCM (jobs.dayforcehcm.com) — API JSON 6 # Rôle : Classe de plateforme Dayforce HCM (jobs.dayforcehcm.com) — API JSON
7 # publique du frontal Next.js, un employeur = une sous-classe 7 # publique du frontal Next.js, un employeur = une sous-classe
8−# Créé : 2026-08-22 Modifié : 2026-08-22 8+# Créé : 2026-08-22 Modifié : 2026-08-26
9 # ============================================================================= 9 # =============================================================================
10 """Plateforme Dayforce HCM (ex-Ceridian) — jobs.dayforcehcm.com. 10 """Plateforme Dayforce HCM (ex-Ceridian) — jobs.dayforcehcm.com.
11 11
@@ -33,6 +33,9 @@ from __future__ import annotations
33 33
34 import os 34 import os
35 import re 35 import re
36+import time
37+
38+import requests
36 39
37 from ..schema import JobPosting, clean_html, is_quebec_location 40 from ..schema import JobPosting, clean_html, is_quebec_location
38 from .base import BaseConnector 41 from .base import BaseConnector
@@ -89,6 +92,30 @@ class DayforceConnector(BaseConnector):
89 "jobDescriptionFooter")) 92 "jobDescriptionFooter"))
90 return {"attributes": attrs, "description": clean_html(desc)} 93 return {"attributes": attrs, "description": clean_html(desc)}
91 94
95+ # -- recherche (garde-fou 5xx transitoire) ------------------------------
96+ def _search_page(self, search_url: str, csrf: str, start: int) -> dict:
97+ """POST de recherche avec garde-fou : le frontal Dayforce renvoie
98+ parfois un 5xx passager (502 Bad Gateway observé le 2026-08-26 sur
99+ groupemaurice) qui avortait tout le sync — on retente une fois après
100+ pause, puis on lève (sync en échec, jamais un faux 0)."""
101+ for attempt in range(2):
102+ try:
103+ return self.post(
104+ search_url,
105+ json={"clientNamespace": self.NS,
106+ "jobBoardCode": self.BOARD,
107+ "cultureCode": self.CULTURE,
108+ "paginationStart": start},
109+ headers={"X-CSRF-TOKEN": csrf,
110+ "Accept": "application/json"}).json()
111+ except requests.HTTPError as e:
112+ status = getattr(e.response, "status_code", 0) or 0
113+ if attempt == 0 and status >= 500:
114+ time.sleep(10)
115+ continue
116+ raise
117+ raise RuntimeError("unreachable")
118+
92 # -- contrat ------------------------------------------------------------ 119 # -- contrat ------------------------------------------------------------
93 def fetch(self) -> list[JobPosting]: 120 def fetch(self) -> list[JobPosting]:
94 csrf = (self.get(f"{BASE}/api/auth/csrf").json() or {}).get( 121 csrf = (self.get(f"{BASE}/api/auth/csrf").json() or {}).get(
@@ -99,12 +126,7 @@ class DayforceConnector(BaseConnector):
99 details_used = 0 126 details_used = 0
100 start = 0 127 start = 0
101 for _ in range(self.max_pages): 128 for _ in range(self.max_pages):
102− data = self.post( 129+ data = self._search_page(search_url, csrf, start)
103− search_url,
104− json={"clientNamespace": self.NS, "jobBoardCode": self.BOARD,
105− "cultureCode": self.CULTURE, "paginationStart": start},
106− headers={"X-CSRF-TOKEN": csrf,
107− "Accept": "application/json"}).json()
108 postings = data.get("jobPostings") or [] 130 postings = data.get("jobPostings") or []
109 if not postings: 131 if not postings:
110 break 132 break
111 133
Menu

Theme