SPB Git forge

spb/fabri-ka

Public

Agrégateur de produits québécois — www.fabri-ka.com

217commits 1branches 0releases
66.1 MBsize
maindefault branch
4 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

[ka6] fix connecteur immunotec.com: retry (4 essais, backoff 5s/10s/15s) sur le POST product-wall Scrapfly — Cloudflare renvoie par intermittence un 200 au corps vide/non-JSON selon l'IP Scrapfly du moment (historique sync_log: ~2 succès sur 12, erreur « Expecting value: line 1 column 1 »), l'API et le parsing sont inchangés (6/6 sondes JSON valides); erreur désormais explicite (statut + extrait du corps) au lieu du json.loads brut. Sync réel: 49 produits / statut ok (= médiane 49.0)

Simon-Pierre Boucher committed 1 mo ago (Aug 24, 2026) parent b5acd1d

1 changed file +19 −6

modified fabrika/connectors/immunotec.py +19 −6
@@ -12,6 +12,7 @@ from __future__ import annotations
12 12
13 13 import json
14 14 import re
15 +import time
15 16 import unicodedata
16 17
17 18 from ..schema import Product, parse_price
@@ -44,12 +45,24 @@ class ImmunotecConnector(BaseConnector):
44 45 "categoryId": category_id, "isConsultant": False,
45 46 "downlineCustomerId": 0, "isShareCart": False,
46 47 "isEnrollment": False}
47 − status, content = scrapfly_post(API_BASE + WALL_PATH, body,
48 − headers=API_HEADERS)
49 − if status != 200:
50 − raise RuntimeError(f"immunotec product-wall {status}")
51 − data = json.loads(content)
52 − return ((data.get("records") or {}).get("items") or []) if data.get("status") else []
48 + # Cloudflare laisse parfois passer un 200 au corps vide/HTML selon
49 + # l'IP Scrapfly du moment : on réessaie avant de déclarer l'échec.
50 + last = "?"
51 + for attempt in range(4):
52 + if attempt:
53 + time.sleep(5 * attempt)
54 + status, content = scrapfly_post(API_BASE + WALL_PATH, body,
55 + headers=API_HEADERS)
56 + if status == 200:
57 + try:
58 + data = json.loads(content)
59 + except ValueError:
60 + last = f"200 non-JSON ({content[:60]!r})"
61 + continue
62 + return ((data.get("records") or {}).get("items") or []) \
63 + if data.get("status") else []
64 + last = f"HTTP {status}"
65 + raise RuntimeError(f"immunotec product-wall: {last} après 4 essais")
53 66
54 67 def _all_category_id(self) -> int:
55 68 """Relit le webCategoryId « Tous les produits » depuis la page du mur."""
56 69