SolidHooksSolidHooks
Commencer
Cas d’usageAcheminer vers plusieurs destinations

Acheminez un webhook vers chaque service qui en a besoin

Stripe envoie un événement de facture une seule fois. Votre service de facturation en a besoin, votre entrepôt de données en veut une copie, et l’agent qui rapproche les comptes aussi. SolidHooks accepte cette requête une fois, stocke le corps brut, puis le diffuse sur toutes les connexions que vous avez définies. Chacune conserve son propre filtre, son propre compteur de tentatives et son propre accusé de réception.
Une seule requête entranteRelances indépendantes par destinationFacturé à la livraison
Contenu de ce guide
  1. 01Comment s’articulent sources, destinations et connexions
  2. 02Filtrer quels événements atteignent quelle destination
  3. 03L’effet de la diffusion sur les relances, le débit et votre facture
  4. 04Rétablir une destination sans perturber les autres
  5. 05Lire la file pendant qu’elle se vide

Trois objets, et seulement trois

Une source est un point de terminaison entrant. Elle possède un maskId et une ingestUrl, et cette URL est le seul identifiant dont votre fournisseur a besoin. Une destination est un endroit où vous voulez envoyer des événements, avec ses propres en-têtes et sa propre limite de débit. Une connexion relie une source à une destination et décide quels événements font le trajet.

La diffusion, c’est ce que vous obtenez quand une source a plus d’une connexion. Rien ne change pour la source et le fournisseur n’en sait jamais rien.

Provider
POST once
Source
verified, stored
Connections
3 matched
Deliveries
3 billed
Le fournisseur reçoit une seule réponse. Tout ce qui suit la source se passe de notre côté : une destination lente ne peut pas amener votre fournisseur à réessayer.

Brancher une deuxième destination

Si une source existe déjà, ajouter un consommateur se résume à une destination et une connexion. Ni l’une ni l’autre ne touche au fournisseur.

  1. 1

    Créez la destination

    POST /v1/destinations avec l’URL à appeler. Les en-têtes personnalisés sont pris en charge, et ceux que vous marquez comme sensibles sont chiffrés au repos et jamais renvoyés par l’API.

  2. 2

    Connectez-la à la source

    Une connexion nomme la paire et restreint éventuellement ce qui y transite. Omettez filterRules.eventTypes pour tout transmettre.

    curl
    curl -s "$API/v1/connections" \  -H "authorization: Bearer $SDHK_KEY" \  -H 'content-type: application/json' \  -d '{    "name": "Stripe → billing service",    "sourceId": "src_...",    "destinationId": "dest_...",    "filterRules": { "eventTypes": ["invoice.payment_succeeded"] }  }'
  3. 3

    Envoyez un événement de test

    Envoyez une requête à l’URL d’ingestion de la source. Une source avec vérification de signature exige une signature valide ; sans elle, la requête reçoit un 401 et est stockée avec le statut rejected. Une fois l’événement arrivé, vous devriez voir deux livraisons associées, une par connexion, chacune avec son propre statut.

Filtrer sans langage de règles

Une connexion filtre sur le type d’événement et rien d’autre. Le type provient du eventTypeField de la source, un chemin en notation pointée dans la requête. Les fournisseurs connus définissent une valeur par défaut adaptée : une source GitHub lit headers.x-github-event et une source Stripe lit le type dans le corps, sans aucune configuration de votre part.

Ce simple réglage couvre plus qu’il n’y paraît, car c’est vous qui choisissez le chemin. Faites pointer une source vers body.action et ses connexions filtrent sur l’action plutôt que sur l’en-tête.

curl
# A GitHub source filters on the event header by default.# Point eventTypeField at a body path to filter on something else:curl -s -X PATCH "$API/v1/sources/src_..." \  -H "authorization: Bearer $SDHK_KEY" \  -H 'content-type: application/json' \  -d '{ "data": { "eventTypeField": "body.action" } }' # Connections on that source now match on the action, not the header:#   "filterRules": { "eventTypes": ["review_requested"] }
Bon à savoir
Un événement exclu par tous les filtres est tout de même stocké, avec le statut filtered. Vous ne l’avez pas perdu. Ajoutez la connexion manquante et rejouez-le.

Ce que coûte la diffusion

L’unité facturable est la livraison : un événement envoyé à une destination connectée. Trois connexions sur un événement représentent trois livraisons. La tarification suit le travail plutôt que le nombre de sièges : ajouter un quatrième consommateur coûte la même chose, qu’une ou quarante personnes consultent le tableau de bord.

événement × connexionUne livraison facturable chacun
nouvelle tentative automatiqueGratuite. Même livraison, une tentative de plus.
relance manuelleGratuite. Aucune nouvelle livraison n’est créée.
rejeu d’événementFacturé. Il crée de nouvelles livraisons sur chaque connexion correspondante.
requête en doubleRien à facturer. Une requête dédupliquée reçoit un 200 et n’atteint jamais la diffusion.

Quand une destination tombe

Les livraisons échouent indépendamment. Chacune est relancée selon une courbe de backoff croissante qui commence à 5 secondes et s’étend jusqu’à 10 heures entre deux tentatives : trois tentatives sous un plafond d’une heure sur Hobby, huit sous un plafond de 36 heures sur les plans payants, que la courbe atteint après environ 28 heures. Ensuite, la livraison vous attend au lieu de disparaître. Les autres connexions du même événement ne sont pas affectées et auront déjà abouti.

Les réponses hors 2xx ne comptent pas toutes comme des échecs, ce qui importe quand vous lisez un journal de tentatives à 3 h du matin.

2xxSuccès.
3xxÉchec. Les redirections ne sont jamais suivies : faites pointer la destination vers son URL finale.
410 GoneDeux 410 consécutifs désactivent la destination et envoient un e-mail à vos propriétaires et administrateurs. Toute autre réponse entre les deux remet le compteur à zéro, tout comme la modification de la destination, car un avertissement appartient à la configuration qui l’a provoqué.
429, 502, 504Mise en attente plutôt qu’échec. Respecte Retry-After jusqu’à une heure et ne consomme aucune tentative. Limité à cinq mises en attente par livraison, et refusé plus tôt si l’attente dépassait le plafond de relance de votre plan ; dans les deux cas, la livraison bascule sur le chemin d’échec.

Deux chemins de rétablissement existent et ils ne sont pas interchangeables. POST /v1/deliveries/{id}/retry renvoie une livraison vers une destination sans rien créer de nouveau : c’est gratuit. POST /v1/events/{id}/replay fait repasser l’événement par ses connexions, ce qui produit de nouvelles livraisons facturées. Utilisez la relance quand un seul consommateur a échoué, et le rejeu quand vous avez ajouté une connexion après coup.

Le rejeu refuse un événement rejeté
Un événement rejected a échoué à la vérification de signature : le rejouer enverrait un contenu non vérifié à vos destinations au nom de cette source. Il renvoie 400. Une requête écartée comme doublon n’est pas stockée du tout : il n’y a donc rien à rejouer non plus.

Le cadencement, qui n’est pas un échec

Deux limites de débit s’appliquent côté sortant : les livraisons par seconde de votre plan, et la limite que vous définissez sur une destination donnée. Dépasser l’une ou l’autre met la livraison en file au lieu de la faire échouer. Son statut indique throttled avec un throttledReason égal à rate_limit, aucune tentative n’est consommée, et elle part dès que de la capacité se libère. Le même statut accompagné de destination_busy désigne l’autre type de pause : la destination l’a demandée par un 429, 502 ou 504.

C’est surtout important quand une destination se rétablit. Un service qui vient de revenir ne reçoit pas tout l’arriéré d’un coup, et vous n’êtes pas alerté pour une file qui se vide normalement. Une livraison qui a été retenue conserve un horodatage throttledAt même après avoir abouti, si bien que la pause reste visible après coup.

curl
# Everything that was excluded by a filtercurl -s "$API/v1/events?status=filtered" -H "authorization: Bearer $SDHK_KEY" # What is waiting in the outbound queue right nowcurl -s "$API/v1/deliveries/stats" -H "authorization: Bearer $SDHK_KEY"→ { "pending": 4, "throttled": 412 }

Bonnes pratiques à adopter

  • Donnez à chaque consommateur sa propre connexion plutôt que d’en partager une et de brancher dans votre gestionnaire. Des connexions séparées vous donnent des états de relance et des accusés de réception séparés.
  • Définissez une limite de débit sur toute destination que vous savez fragile. Mettre en file coûte moins cher aux deux parties qu’une rafale d’échecs suivie d’un backoff.
  • Filtrez au niveau de la connexion, pas dans votre gestionnaire. Un événement que votre service allait ignorer coûte quand même une livraison si vous le laissez passer.
  • Consultez ?status=filtered quand un consommateur signale des événements manquants. La cause habituelle est un eventTypeField qui pointe ailleurs que là où vous le pensiez.
  • Rendez vos gestionnaires idempotents. Le rejeu existe, on s’en sert pendant les incidents, et votre point de terminaison doit traiter une deuxième copie comme une opération sans effet.

Questions

Diffusez une source vers tout ce qui en a besoin

Créez une source, ajoutez autant de connexions que vous avez de consommateurs, et regardez chacune se stabiliser.