Erreurs, retries et idempotence
Ormuz sépare trois problèmes : rejouer automatiquement une opération transitoirement indisponible, créer une continuation opérateur après une instance terminale, et empêcher qu’un même déclenchement ou effet externe soit dupliqué. Ces mécanismes ont des garanties différentes et ne doivent pas être confondus.
Retry automatique d’un node
Une erreur ne devient un retry durable que si elle est reconnue comme transitoire et si l’opération est sûre à rejouer. Sinon le node échoue immédiatement.
Lorsqu’un node échoue, Ormuz classe l’erreur avant toute nouvelle tentative. Une erreur explicitement déclarée rejouable peut être transformée en attente durable : le node reste waiting, une échéance de retry est enregistrée et la même invocation logique est reprise plus tard.
Une erreur inconnue n’est pas supposée transitoire. Elle devient terminale sauf si la capacité qui l’a produite a fourni un signal explicite permettant au runtime de savoir qu’un replay est sûr.
Budget de retry
Le budget effectif part d’une politique plateforme, peut être configuré au niveau du processus, puis seulementresserré par un node. Un node ne peut pas s’accorder davantage de temps ou de tentatives que le processus qui le contient.
Le budget combine un plafond de tentatives et une deadline totale. Les délais entre tentatives sont bornés et peuvent respecter un Retry-After fourni par le système externe. Quand la deadline ou le plafond est épuisé, le step devient failed avec l’indication d’épuisement et l’instance peut atteindreretry_exhausted.
Wait autour d’une opération déjà couverte par cette politique.Sûreté du replay
Une lecture HTTP idempotente peut être rejouée sans créer un nouvel effet. Une écriture réseau n’est en revanche rejouable automatiquement que si Ormuz peut établir qu’elle n’a pas été envoyée, ou si l’appel est prot égé par une clé d’idempotence, ou si la capacité elle-même déclare explicitement un retry sûr.
Cette règle évite un piège classique : transformer un timeout ambigu en double paiement, double e-mail ou double création provider. La simple présence d’une erreur réseau ne constitue donc pas une autorisation de replay.
Trois continuations opérateur différentes
| Action | Source autorisée | Révision utilisée | Continuité |
|---|---|---|---|
retry | failed / retry_exhausted / stopped | Working courant | Même input ; état d’exécution neuf ; continuité de la ressource process-owned transférée quand elle est encore éligible. |
rerun | instance terminale | Working courant | Même input, nouvel environnement et nouvelle exécution indépendante ; ne reprend pas l’ownership métier de la source. |
fork | instance disposant du checkpoint demandé | Révision de l’instance source | Repart autour d’un node choisi en reconstruisant un état cohérent depuis l’audit de la source. |
Ces opérations créent toutes une nouvelle instance. Elles ne remettent pas l’ancienne instance à running et ne réécrivent pas son audit.
Retry manuel
POST /v1/process-instances/:id/retry est disponible pour une instance failed, retry_exhausted ou stopped. La nouvelle instance reprend le même input mais utilise la Working revision courante de la définition, pas nécessairement la révision qui avait échoué.
POST /v1/process-instances/pci_123/retry
Les participants et la protection attachée à l’input sont conservés. Pour une ressource métier dont le processus était propriétaire, l’ownership peut être transféré vers cette nouvelle tentative ; une instance arrêtée explicitement ne récupère pas automatiquement cet ownership lors du retry.
Run again
POST /v1/process-instances/:id/rerun crée une exécution indépendante à partir du même input sur la Working revision courante. Il est disponible pour les instances terminales, y compris une exécution réussie.
POST /v1/process-instances/pci_123/rerun
Le rerun repart avec un état de nodes et de variables neuf, reconstruit son snapshot d’environnement et ne devient pas le successeur métier de la ressource process-owned de la source. Utilisez-le lorsque le besoin est « lancer à nouveau ce processus aujourd’hui », pas « réparer cette tentative ».
Fork ciblé
POST /v1/process-instances/:id/fork crée une continuation qui reste épinglée à la révision de l’instance source. Elle reconstruit un état cohérent autour d’un node choisi et garde fork_of pour relier les deux instances.
POST /v1/process-instances/pci_123/fork
{
"action": "retry_step",
"node_id": "send_to_provider",
"reason": "Rejouer l’appel après correction externe"
}action peut valoir retry_step, skip_step ou resume_after_step. Le dernier mode nécessite un step complété utilisable comme checkpoint : Ormuz restaure alors l’état audité après cette étape avant de poursuivre.
Un fork ne permet pas de modifier arbitrairement l’historique. Il crée une nouvelle branche de la lignée avec une provenance explicite et laisse la source intacte.
Lignée, superseded et ownership métier
Les champs retry_of, fork_of et les informations de start_source permettent de reconstruire la relation entre les instances. Une continuation corrective peut rendre une tentative antérieure superseded lorsque la nouvelle instance devient celle qui poursuit le traitement.
Pour les ressources process-owned, une seule instance doit piloter le traitement courant. Les continuations qui ont vocation à réparer cette exécution peuvent transférer ce rôle ; un rerun indépendant ne le récupère pas. Consultez la vue Observabilité pour suivre cette lignée.
Idempotence de déclenchement
L’idempotence d’une opération provider et la déduplication d’une instance sont deux garanties différentes. Un launcher événementiel déduplique automatiquement un même événement pour un même launcher afin qu’une livraison répétée ne crée pas plusieurs instances identiques.
Le lancement direct POST /v1/processes/:id/runs représente au contraire une nouvelle demande d’exécution à chaque appel. Si votre intégration a besoin d’une création d’instance explicitement dédupliquée, utilisez le contrat d’instance qui expose une dedupe_key plutôt que d’inventer une clé dans le payload du endpoint /runs.