SPB Git forge

spb/job-ka

Public
229commits 1branches 0releases
38.1 MBsize
maindefault branch
4 h agolast push
HTML 82.1% Python 14.6% TypeScript 1.9% CSS 1% JavaScript 0.5%

[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 29 days ago (Aug 27, 2026) parent f4038e4

1 changed file +29 −7

modified jobka/connectors/dayforce.py +29 −7
@@ -5,7 +5,7 @@
5 5 # Fichier : jobka/connectors/dayforce.py
6 6 # Rôle : Classe de plateforme Dayforce HCM (jobs.dayforcehcm.com) — API JSON
7 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 10 """Plateforme Dayforce HCM (ex-Ceridian) — jobs.dayforcehcm.com.
11 11
@@ -33,6 +33,9 @@ from __future__ import annotations
33 33
34 34 import os
35 35 import re
36 +import time
37 +
38 +import requests
36 39
37 40 from ..schema import JobPosting, clean_html, is_quebec_location
38 41 from .base import BaseConnector
@@ -89,6 +92,30 @@ class DayforceConnector(BaseConnector):
89 92 "jobDescriptionFooter"))
90 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 119 # -- contrat ------------------------------------------------------------
93 120 def fetch(self) -> list[JobPosting]:
94 121 csrf = (self.get(f"{BASE}/api/auth/csrf").json() or {}).get(
@@ -99,12 +126,7 @@ class DayforceConnector(BaseConnector):
99 126 details_used = 0
100 127 start = 0
101 128 for _ in range(self.max_pages):
102 − data = self.post(
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()
129 + data = self._search_page(search_url, csrf, start)
108 130 postings = data.get("jobPostings") or []
109 131 if not postings:
110 132 break
111 133