SPB Git

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

[ka2] fix connecteur groupe_robin: timeouts admin-ajax récurrents retryables sur le POST liste. Au sync de 11:45 le connecteur a échoué (stale) sur un ReadTimeout 30 s — 3e épisode du même hoquet (ConnectTimeout 09-13, ReadTimeout 10-17 et 10-28) sur le POST admin-ajax get_list_immeubles_ajx dont la réponse pèse ~3,9 Mo (backend WP parfois lent), alors que le connecteur est sain (found=62 stable, re-testé live : 200 en 3-5 s ×3). Les deux missions précédentes avaient conclu « transitoire, rien à faire » : le hoquet revient — fix minimal (patron morin ae6ac03) : _post_ajax fait désormais 3 tentatives avec backoff 0/5/10 s sur Timeout/ConnectionError/HTTP 5xx (4xx propagés tels quels), erreur franche inchangée si les 3 échouent (pas de zéro silencieux) ; timeout de classe porté 30 → 60 s pour le payload lourd. Fixtures inchangées, pytest groupe_robin 2 passed. Testé : fetch() venv → 62 unités (715-2 190 $, T-R 39 / St-Hyacinthe 23), run.py sync groupe_robin → found=62 ok (added=0, updated=0, removed=0, 3,5 s) = médiane exacte 62.0, pm2 restart lou-ka-sync, site :8095 → 200.

Simon-Pierre Boucher committed (Oct 28, 2026) parent 8015617 Browse files

1 changed file +31 −12

Unified Split
modified louka/connectors/groupe_robin.py +31 −12
@@ -15,6 +15,7 @@ from __future__ import annotations
15 import re 15 import re
16 import time 16 import time
17 17
18+import requests
18 from bs4 import BeautifulSoup 19 from bs4 import BeautifulSoup
19 20
20 from ..schema import Listing, normalize_unit_type 21 from ..schema import Listing, normalize_unit_type
@@ -64,21 +65,39 @@ class GroupeRobinConnector(BaseConnector):
64 source_id = "groupe_robin" 65 source_id = "groupe_robin"
65 request_delay = 0.8 66 request_delay = 0.8
66 max_pages = 5 # garde-fou (2 pages réelles à 40 immeubles/page) 67 max_pages = 5 # garde-fou (2 pages réelles à 40 immeubles/page)
68+ timeout = 60 # payload admin-ajax ~3,9 Mo, backend WP parfois lent
67 69
70+ # Le POST admin-ajax (3,9 Mo) hoquète par épisodes (ReadTimeout isolés
71+ # 09-13, 10-17, 10-28) alors que le site est sain entre deux — 3
72+ # tentatives avec backoff ; erreur franche inchangée si les 3 échouent.
68 def _post_ajax(self, offset: int) -> list: 73 def _post_ajax(self, offset: int) -> list:
69 """POST admin-ajax paginé, avec la même politesse que get().""" 74 """POST admin-ajax paginé, avec la même politesse que get()."""
70− wait = self.request_delay - (time.time() - self._last_request) 75+ last: Exception | None = None
71− if wait > 0: 76+ for attempt in range(3):
72− time.sleep(wait) 77+ if attempt:
73− resp = self.session.post(AJAX_URL, data={ 78+ time.sleep(5 * attempt)
74− "action": "get_list_immeubles_ajx", 79+ wait = self.request_delay - (time.time() - self._last_request)
75− "offset": str(offset), 80+ if wait > 0:
76− "immeubles_per_page": str(PER_PAGE), 81+ time.sleep(wait)
77− "categories[]": CAT_APPARTEMENT, 82+ try:
78− }, timeout=self.timeout) 83+ resp = self.session.post(AJAX_URL, data={
79− self._last_request = time.time() 84+ "action": "get_list_immeubles_ajx",
80− resp.raise_for_status() 85+ "offset": str(offset),
81− return resp.json() 86+ "immeubles_per_page": str(PER_PAGE),
87+ "categories[]": CAT_APPARTEMENT,
88+ }, timeout=self.timeout)
89+ except (requests.Timeout, requests.ConnectionError) as exc:
90+ self._last_request = time.time()
91+ last = exc
92+ continue
93+ self._last_request = time.time()
94+ if resp.status_code >= 500:
95+ last = requests.HTTPError(
96+ f"{resp.status_code} sur {AJAX_URL}", response=resp)
97+ continue
98+ resp.raise_for_status()
99+ return resp.json()
100+ raise last # type: ignore[misc]
82 101
83 def fetch(self) -> list[Listing]: 102 def fetch(self) -> list[Listing]:
84 listings: dict[str, Listing] = {} 103 listings: dict[str, Listing] = {}
85 104
Menu

Theme