SPB Git forge

spb/lou-ka

Public

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

232commits 1branches 0releases
172.9 MBsize
maindefault branch
2 days agolast push
HTML 98.9% Python 0.6%

[ka2] fix connecteur louis14: retry (3 essais, backoff 5/10 s) de la page Livya — un 500 transitoire de app.livya.com (vu 2026-08-30 ~13:42) faisait échouer tout le sync au premier essai (médiane 19); désormais retry court puis erreur franche si le flux RSC ne livre aucune unité après 3 essais (garde contre un 200 vide qui dépublierait l'inventaire en « 0 trouvé ok »). Testé: run.py sync louis14 → 19 annonces (= médiane 19) + tests fixtures OK

Simon-Pierre Boucher committed 25 days ago (Aug 30, 2026) parent 656d1f5

1 changed file +29 −8

modified louka/connectors/louis14.py +29 −8
@@ -16,6 +16,7 @@ from __future__ import annotations
16 16
17 17 import json
18 18 import re
19 +import time
19 20
20 21 from ..schema import Listing, normalize_unit_type
21 22 from .base import BaseConnector
@@ -65,15 +66,35 @@ class Louis14Connector(BaseConnector):
65 66
66 67 def fetch(self) -> list[Listing]:
67 68 client, project, entity, lang = self._module_params()
68 − html = self.get(
69 − f"{LIVYA}/{lang}/{client}/projects/{project}/plans/{entity}").text
69 + url = f"{LIVYA}/{lang}/{client}/projects/{project}/plans/{entity}"
70 70
71 − # flux RSC : les fragments sont des corps de chaînes JSON — les
72 − # recoller puis décoder donne le JSON des unités en clair
73 − blob = "".join(json.loads(f'"{c}"') for c in _FLIGHT_RE.findall(html))
74 −
75 − buildings = self._buildings(blob)
76 − units = self._units(blob)
71 + # Un raté transitoire de la page Livya (500, vu 2026-08-30 ~13:42)
72 + # faisait échouer tout le sync au premier essai : retry court
73 + # (backoff 5/10 s), puis erreur franche si le flux RSC ne livre
74 + # aucune unité (plutôt qu'un [] qui dépublierait l'inventaire).
75 + units: list[dict] = []
76 + buildings: dict[str, str] = {}
77 + for attempt in range(3):
78 + try:
79 + html = self.get(url).text
80 + # flux RSC : les fragments sont des corps de chaînes JSON —
81 + # les recoller puis décoder donne le JSON des unités en clair
82 + blob = "".join(
83 + json.loads(f'"{c}"') for c in _FLIGHT_RE.findall(html))
84 + buildings = self._buildings(blob)
85 + units = self._units(blob)
86 + except Exception:
87 + if attempt == 2:
88 + raise
89 + else:
90 + if units:
91 + break
92 + if attempt < 2:
93 + time.sleep(5 * (attempt + 1))
94 + if not units:
95 + raise RuntimeError(
96 + f"aucune unité dans le flux RSC après 3 essais ({url}) — "
97 + "format Livya changé ?")
77 98
78 99 listings: list[Listing] = []
79 100 for u in units[: self.max_units]:
80 101