ENbext.dev
DocumentationInclusions côté serveur

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Délai d'attente et repli

Une page est aussi fiable que les sources qu’elle contient. Une API en amont qui est lente ou en panne ne devrait pas bloquer la page entière ou la surface en tant que balisage cassé. bext fournit quatre niveaux de résilience : délais d'attente, chaînes de repli, stratégies d'erreur et disjoncteurs, tous déclaratifs sur l'inclusion.

html
<bext-include src="/api/live-scores"
  timeout="200ms"
  fallback="/_partials/cached-scores.html"
  fallback-2="/_partials/default-scores.html"
  onerror="continue"
>Scores unavailable</bext-include>

Abandonnez après 200 ms ; essayez deux solutions de secours ; abandonnez silencieusement si tout échoue ; afficher un message convivial si JS est désactivé. Chaque comportement est un attribut.

Les couches#

code
Primary src
  ↓ (fails or times out)
fallback  ────── tries another source path
  ↓ (fails)
fallback-2 ───── tries a second source path
  ↓ (fails)
inline content  — uses content between open/close tags
  ↓ (no inline)
onerror strategy
  ├── "continue" → return empty string (include disappears)
  └── "abort"   → leave the <bext-include> tag as-is

Chaque couche est indépendante. Définissez uniquement ce dont vous avez besoin.

Délais d'attente#

html
<bext-include src="/api/recommendations"
  timeout="200ms"
></bext-include>
Format Attendre maximum
100ms 100 millisecondes
500ms 500 millisecondes
1s 1 seconde
5s 5 secondes

Lorsque le résolveur interne prend plus de temps que le délai d'attente, bext l'annule et le traite comme un échec, en passant à la chaîne de secours.

Plages de délais d'attente utiles :

  • Cache / fichiers partiels : aucun délai d'attente nécessaire (la résolution est de quelques microsecondes).
  • V8 rend : 200 ms-500 ms (dépend de la complexité des composants).
  • HTTP en amont récupère : 100 ms-1s (dépend du SLA).
  • Requêtes de base de données : 200 ms-500 ms.

Le délai d'expiration par défaut provient de la configuration :

toml
[include.timeouts]
default = "5s"      # global fallback
proxy = "3s"        # for upstream fetches
v8 = "500ms"        # for V8 renders

Les attributs timeout par inclusion les remplacent.

Chaîne de repli#

Lorsque la source principale échoue ou expire, bext essaie fallback. Si cela échoue également, fallback-2. Chacun est un src complet — ils peuvent pointer n'importe où : fichiers, points de terminaison, rendus V8.

html
<bext-include src="/api/live-prices"
  fallback="/cache/prices/latest"
  fallback-2="/_partials/default-prices.html"
  timeout="100ms"
></bext-include>
  • Essayez /api/live-prices avec un délai d'attente de 100 ms.
  • En cas d'expiration/d'échec, essayez /cache/prices/latest.
  • Au deuxième échec, essayez /_partials/default-prices.html.
  • Si tout échoue, utilisez le contenu en ligne ou appliquez onerror.

Les solutions de secours passent par la même chaîne de résolution que la chaîne principale — de sorte que votre solution de secours peut elle-même être mise en cache, authentifiée ou rendue via V8. Ils ne sont pas spéciaux, il s'agit simplement de chemins alternatifs dans le pipeline normal.

Remplacement en ligne#

Le contenu entre <bext-include> et </bext-include> constitue la solution de secours en dernier recours :

html
<bext-include src="/api/comments" timeout="500ms">
  <p class="error">Comments couldn't load. <a href="">Retry?</a></p>
</bext-include>

Si la source principale et toutes les solutions de secours configurées échouent, le contenu en ligne est émis. Cela sert également d’espace réservé pour loading="lazy" – un élément de contenu sert donc à deux fins.

stratégies d'erreur#

html
<!-- Silently drop on total failure -->
<bext-include src="/unknown" onerror="continue"></bext-include>

<!-- Leave the tag as-is on failure (debugging) -->
<bext-include src="/unknown" onerror="abort"></bext-include>
Stratégie Comportement
continue Émettre une chaîne vide ; inclure "disparaît" du HTML
abort (par défaut) Laissez la balise <bext-include> telle quelle dans la réponse

continue est la bonne valeur par défaut pour les inclusions non critiques (barres latérales, décorations, recommandations). abort est utile dans le développement où vous souhaitez voir quelles inclusions ont échoué.

L'attribut onerror="continue" d'ESI correspond au même comportement pour les balises ESI.

Conseil

Les sources de secours passent par la même chaîne de résolution que la source principale : une solution de secours peut donc elle-même être un fichier partiel mis en cache, un rendu V8 ou un autre point de terminaison. La chaîne n'a pas de traitement spécial pour "ceci est une solution de secours".

Disjoncteur#

Si une source tombe en panne à plusieurs reprises, le disjoncteur s'ouvre : les requêtes suivantes ignorent complètement la source et passent directement au repli, sans attendre l'expiration du délai d'attente.

toml
[include.circuit_breaker]
enabled = true
failure_threshold = 5     # failures before opening
cooldown = "30s"          # time before retrying
half_open_requests = 1    # test requests in half-open state

États des circuits#

code
          ┌─────────────┐
          │   Closed    │  Normal operation.
          │             │  Failures count toward threshold.
          └──────┬──────┘
                 │ N failures
                 ↓
          ┌─────────────┐
          │    Open     │  Skip resolution, go straight to fallback.
          │             │  No timeout overhead.
          └──────┬──────┘
                 │ cooldown expires
                 ↓
          ┌─────────────┐
          │  Half-open  │  Allow one request through.
          │             │  Success → Closed. Failure → Open.
          └─────────────┘

Une fois le circuit ouvert, les requêtes n'essaient même pas la source défaillante : elles vont directement vers la solution de repli. Cela protège à la fois votre page (pas de pénalité de latence dès le timeout de 500 ms) et l'amont défaillant (pas d'amplification lors d'une panne).

Isolement par source#

L’état du circuit est par chemin source. Un circuit ouvert sur /api/feed-a n'affecte pas /api/feed-b. Certaines sources peuvent être à l’état Ouvert tandis que d’autres sont saines.

Réinitialisation manuelle#

bash
# Reset a specific source's circuit
curl -X POST http://localhost/__bext/include/circuit/reset \
  -d '{"src":"/api/feed-a"}'

Utile après avoir résolu un problème en amont : force le circuit à revenir en mode Fermé sans attendre le temps de recharge.

Attention

Une fois que le circuit est ouvert pour une source, les requêtes la contournent entièrement et passent en mode de repli : aucun délai d'attente n'est encouru. Le circuit reste ouvert pendant la période cooldown configurée. Après le temps de recharge, une seule demande de sonde est autorisée ; le succès ferme le circuit, l’échec le rouvre.

Enregistrement#

Chaque délai d'attente, repli et changement d'état du circuit est enregistré :

code
WARN include timeout: src=/api/recommendations timeout=200ms elapsed=201ms
WARN include fallback: src=/api/recommendations → /cache/recommendations
WARN circuit opened for /api/feed after 5 failures (cooldown 30s)
INFO circuit closed for /api/feed after successful recovery

Ceux-ci alimentent la pile d'observabilité de bext : vous pouvez alerter en cas de circuits ouverts, suivre les taux de repli et mesurer les violations des SLA au niveau d'inclusion.

Exemples pratiques#

API en amont avec repli de mise en cache agressif#

html
<bext-include src="/api/leaderboard"
  timeout="150ms"
  fallback="/_partials/leaderboard-cache.html"
  ttl="30s"
  tags="leaderboard"
></bext-include>

Données fraîches de l'API avec un budget de 150 ms ; revenez à un fichier cache pré-généré en cas de réponses lentes. Mettez en cache le résultat pendant 30 secondes afin que les N prochains téléspectateurs obtiennent le chemin rapide.

Décoration non critique#

html
<bext-include src="/api/weather-widget"
  timeout="100ms"
  onerror="continue"
></bext-include>

La météo est agréable à montrer mais pas critique. Budget de 100 ms ; si l'API est en panne, le widget n'apparaît tout simplement pas.

Données financières avec SLA strict#

html
<bext-include src="/api/live-price"
  timeout="50ms"
  fallback="/api/last-known-price"
  fallback-2="/_partials/price-unavailable.html"
>
  <div class="price-placeholder">—</div>
</bext-include>

Budget dur de 50 ms (SLA). Revenir au dernier prix connu. Si même cela échoue, affichez "prix indisponible". L'espace réservé en ligne affiche un tiret si tout échoue.

Rendu avec protection contre l'expiration du délai#

html
<bext-include src="./components/HeavyChart.tsx"
  render="v8"
  props='{"data":"..."}'
  timeout="300ms"
  fallback="/_partials/chart-fallback.html"
></bext-include>

Rendu V8 avec un budget de 300 ms. Si le composant prend trop de temps, revenez à un graphique statique pré-rendu.

Voir aussi#

Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.