[ka2] fix connecteur le_fjord: échec honnête au lieu d'un « 0 trouvé ok » qui aurait dépublié les 68 unités. Le sync du 2026-09-06 19:15 a rapporté found=0 ok=1 (dérive vs médiane 68, retraits suspendus par le garde-fou) : le fetch() avalait toute exception sur app.livya.com (`except Exception: return []`) et retournait aussi [] en silence si le flux RSC Next.js ne contenait pas le tableau "units" (rendu partiel 200) ou si le JSON était illisible — une erreur transitoire devenait un succès à 0 résultat, invisible du disjoncteur d'ingest.py. Reproduit en live : la page plans Livya répond 200 (596 Ko) et les 68 unités se parsent — la source est saine, seul le silence sur erreur était fautif. On laisse désormais l'exception réseau remonter (ingest journalise ok=0) et on lève RuntimeError si "units" est absent/tronqué/illisible (même pattern que les fix gwlra et cinquante_ans_plus). Testé : run.py sync le_fjord → found=68 ok (Unité 908 3 045 $, Unité 907 2 970 $), pm2 restart lou-ka-sync, site :8095 → 200.
1 changed file +15 −8
modified
louka/connectors/le_fjord.py
+15 −8
@@ -58,22 +58,29 @@ class LeFjordConnector(BaseConnector): | ||
| 58 | 58 | request_delay = 0.6 |
| 59 | 59 | |
| 60 | 60 | def fetch(self) -> list[Listing]: |
| 61 | + # échec HONNÊTE : une erreur réseau ou un rendu Next.js partiel (200 | |
| 62 | + # sans tableau "units" dans le flux RSC) doit lever (ok=0 dans | |
| 63 | + # sync_log) et non retourner [] — un « 0 trouvé ok » dépublierait les | |
| 64 | + # 68 unités (dérive vue le 2026-09-06 19:15) | |
| 61 | 65 | listings: list[Listing] = [] |
| 62 | − try: | |
| 63 | − html = self.get(LIVYA_URL).text | |
| 64 | − except Exception: | |
| 65 | − return listings | |
| 66 | + html = self.get(LIVYA_URL).text | |
| 66 | 67 | payload = _rsc_payload(html) |
| 67 | 68 | i = payload.find(UNITS_KEY) |
| 68 | 69 | if i < 0: |
| 69 | − return listings | |
| 70 | + raise RuntimeError( | |
| 71 | + "app.livya.com (le-fjord) : flux RSC sans tableau \"units\" " | |
| 72 | + "(rendu partiel ou page restructurée)") | |
| 70 | 73 | arr = _balanced_array(payload, i + len(UNITS_KEY) - 1) |
| 71 | 74 | if not arr: |
| 72 | − return listings | |
| 75 | + raise RuntimeError( | |
| 76 | + "app.livya.com (le-fjord) : tableau \"units\" tronqué dans " | |
| 77 | + "le flux RSC") | |
| 73 | 78 | try: |
| 74 | 79 | units = json.loads(arr) |
| 75 | − except ValueError: | |
| 76 | − return listings | |
| 80 | + except ValueError as e: | |
| 81 | + raise RuntimeError( | |
| 82 | + "app.livya.com (le-fjord) : tableau \"units\" illisible " | |
| 83 | + f"({e})") from e | |
| 77 | 84 | |
| 78 | 85 | seen: set[str] = set() |
| 79 | 86 | for u in units: |
| 80 | 87 | |