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

Erreur du node
Rejouable et sûre ?
Retry timer waiting
Échec terminal
Nouvelle tentative du même 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.

Un retry durable est une attente, pas une boucle occupée Entre deux tentatives, l’instance est en attente. Le temps de backoff fait partie du contrat observable de reprise ; il n’est pas nécessaire de rajouter un node 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.

Retryable ≠ sans effet secondaire La sécurité vient du contrat de replay, pas du mot « transitoire ». Pour une opération d’écriture, vérifiez la stratégie d’idempotence documentée par le node ou l’extension concernée.

Trois continuations opérateur différentes

ActionSource autoriséeRévision utiliséeContinuité
retryfailed / retry_exhausted / stoppedWorking courantMême input ; état d’exécution neuf ; continuité de la ressource process-owned transférée quand elle est encore éligible.
reruninstance terminaleWorking courantMême input, nouvel environnement et nouvelle exécution indépendante ; ne reprend pas l’ownership métier de la source.
forkinstance disposant du checkpoint demandéRévision de l’instance sourceRepart 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é.

HTTP
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.

Retry manuel ≠ reproduction historique exacte Si la définition Working a changé depuis l’instance source, le retry exécute ce nouveau snapshot. Utilisez un fork lorsque vous devez rester sur la révision historique de la source.

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.

HTTP
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.

HTTP
POST /v1/process-instances/pci_123/fork
{3 items
"action":"retry_step"
"node_id":"send_to_provider"
"reason":"Rejouer l’appel après correction externe"
}
{
  "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.