Un traitement écrit les ventes du jour dans votre entrepôt. La connexion tombe juste après l’écriture, avant que l’orchestrateur reçoive la confirmation. Il relance la tâche. Si celle-ci ajoute les mêmes lignes une deuxième fois, le pipeline peut finir au vert avec un chiffre d’affaires faux.
L’orchestration data organise le déclenchement, les dépendances et les reprises des traitements. La fiabilité dépend aussi de ce que chaque traitement écrit lorsqu’il est relancé. Airflow ou Dagster ne peuvent pas corriger une insertion qui double les données.
Ce guide propose une méthode pour définir ce comportement, choisir les contrôles utiles et tester les incidents. L’atelier Python téléchargeable fonctionne localement, sans compte cloud. Il a été exécuté sur des données fictives ; il ne constitue ni un benchmark ni un test de déploiement d’Airflow ou de Dagster. Documentation et tarifs vérifiés le 4 octobre 2026.
Orchestration, transformation et qualité : trois responsabilités
L’orchestrateur répond à des questions d’exécution : quel traitement peut démarrer, après lequel, pour quelle période, avec combien de tentatives ? Le code de transformation calcule les données. Les contrôles vérifient ce qui peut être livré aux utilisateurs.
Une dépendance entre deux tâches garantit un ordre selon les règles configurées. Elle ne garantit pas que le fichier reçu est complet ou que les montants sont justes. Un statut réussi doit donc correspondre à une livraison définie : partition présente, contrôles passés, version de source identifiée.
Dans une équipe française qui alimente des tableaux de bord quotidiens, distinguez la date métier, le moment d’arrivée du fichier et l’heure d’exécution. Une vente du jeudi peut être chargée le vendredi puis corrigée le lundi. Ces trois passages concernent la même partition métier.
Définissez explicitement le fuseau, par exemple Europe/Paris pour une journée commerciale locale. Ne déduisez pas la date à recalculer de l’heure courante du serveur. Lors des changements d’heure, une journée locale ne correspond pas toujours à vingt-quatre heures UTC : les bornes doivent suivre le contrat de la source.
Retry, rejeu et backfill : préciser ce que l’on demande
Un retry est une nouvelle tentative après un échec. Un rejeu peut également être volontaire, par exemple pour contrôler un résultat. Un backfill traite une plage historique absente ou à recalculer.
La bonne question est : « Quelle version de quelles journées voulons-nous obtenir ? » Elle évite une relance globale qui mélange un incident réseau, un changement de calcul et un fichier corrigé.
Dans Airflow, le backfill actuel permet de choisir le comportement face aux exécutions existantes et de limiter le nombre de runs simultanés. Dans Dagster, on peut sélectionner les partitions à matérialiser ; par défaut, un backfill de N partitions crée N runs. Une politique spécifique permet un traitement groupé, à condition que le code gère cette plage. Ce sont des mécanismes documentés, pas des nouveautés annoncées aujourd’hui. Airflow : backfill, Dagster : backfills.
Définir une écriture idempotente
Une opération est idempotente si la répéter avec les mêmes entrées et la même logique laisse le même résultat métier. Le journal peut contenir plusieurs tentatives ; la table des ventes ne doit pas grossir pour cette seule raison.
Les bonnes pratiques Airflow recommandent notamment de cibler une partition explicite et d’éviter les insertions qui dupliquent les lignes lors d’une reprise. Elles invitent aussi à stabiliser les entrées utilisées. Documentation Airflow.
Deux stratégies répondent à des contrats différents :
- Remplacer une partition complète : la source représente toute une journée. Le remplacement doit inclure les suppressions et corrections de cette journée.
- Appliquer des changements par clé : la source contient un delta. Il faut gérer les mises à jour, les suppressions et l’ordre des versions. Un simple ajout ne suffit pas.
Ne remplacez pas une journée entière avec un fichier contenant seulement ses nouvelles commandes. À l’inverse, un upsert seul ne supprime pas les commandes retirées d’un snapshot complet. Le contrat de données doit préciser cette différence avant de choisir le SQL.
Cas concret : corriger les ventes sans toucher au lendemain
Prenons une enseigne fictive. Le fichier complet du 1er octobre contient A01 pour 10 € et A02 pour 25 €. Celui du 2 octobre contient B01 pour 9 €. La source corrige ensuite le premier fichier : A01 passe à 12 € et A02 disparaît.
Le résultat attendu pour le 1er octobre est une seule commande à 12 €, pas trois lignes, ni deux lignes à 37 €. La journée du 2 doit rester intacte. Cela oblige à tester autre chose qu’un simple nombre de lignes : identifiants, montants, suppression attendue et isolation de la partition voisine.
Autre situation, toujours fictive : une direction financière change une règle de calcul pour un trimestre. Le backfill utilise alors une nouvelle version de code, avec un périmètre approuvé et un rapprochement des totaux. Il ne s’agit pas d’un retry automatique sur les anciennes entrées. Il faut garder les preuves de l’ancienne version et décider quand les consommateurs peuvent lire la nouvelle.
Tutoriel : provoquer les pannes avant la production
1. Lancer la démonstration locale
Prérequis : Python 3.10 ou plus, avec le module standard sqlite3. Aucun paquet supplémentaire ni service payant n’est nécessaire. Téléchargez le script atelier_reprise.py, puis lancez-le dans un dossier de travail :
python3 atelier_reprise.py --demo --output preuve-reprise.json
Le script crée une base temporaire, joue les scénarios, écrit le rapport puis supprime cette base de démonstration. Le résultat de notre exécution contient 14 vérifications réussies. Il s’agit de tests fonctionnels locaux, sans mesure de débit ni comparaison de performances.
2. Comprendre la frontière de validation
Le chargement valide d’abord la source : date attendue, identifiants uniques, montants entiers en centimes, snapshot non vide. Il remplace ensuite les ventes et leurs métadonnées dans une même transaction.
Le cœur du mécanisme est le suivant ; le fichier téléchargeable inclut les contrôles, les paramètres SQL et la gestion des exceptions :
BEGIN IMMEDIATE;
DELETE FROM ventes WHERE jour = ?;
-- Insérer le snapshot complet de cette journée.
-- Enregistrer son empreinte et sa version de calcul.
COMMIT;
Si une exception survient avant COMMIT, le script déclenche ROLLBACK. Si la validation a déjà eu lieu, une erreur ultérieure ne doit pas faire croire que les données n’ont jamais été écrites. SQLite documente ces frontières de transaction ainsi que la limitation à un seul écrivain simultané. Transactions SQLite.
Le tutoriel stocke les montants en centimes pour éviter les approximations des nombres flottants sur cet exemple. Ce choix ne remplace pas une politique de devises, de taxes et d’arrondis pour votre système réel.
3. Lire les scénarios et leurs résultats
La démonstration effectue notamment ces contrôles :
- Charger puis rejouer le snapshot initial laisse exactement A01 à 1 000 centimes et A02 à 2 500.
- Une exception injectée après DELETE, avant COMMIT, conserve ces lignes et le total de 3 500 centimes.
- Une exception après COMMIT laisse la correction validée : A01 à 1 200 centimes, A02 supprimée.
- Rejouer la correction conserve ce résultat et laisse B01 inchangée.
- Un backfill séquentiel des deux jours, avec B01 corrigée à 950 centimes, donne un total de 2 150 centimes.
- Une source dupliquée, vide, affectée à une autre date ou contenant un montant négatif est refusée sans altérer les ventes présentes.
Ces pannes sont simulées par des exceptions Python. Le test ne coupe pas une machine et ne valide pas la résistance de votre stockage à une panne matérielle.
Le journal conserve douze tentatives, dont les erreurs. Une tentative supplémentaire et un résultat dupliqué sont deux choses différentes. L’empreinte de la source matérialisée permet également de vérifier quelle entrée a produit la partition courante.
4. Essayer un fichier distinct
Téléchargez le snapshot fictif du 1er octobre. Dans un dossier de test, utilisez une nouvelle base :
python3 atelier_reprise.py --db essai.sqlite --date 2026-10-01 --source ventes-2026-10-01.json
Exécutez deux fois la commande. Comparez le champ rows renvoyé : le contenu reste identique, tandis que l’identifiant de tentative change. Pour injecter une panne, ajoutez --fail before_commit ou --fail after_commit, puis relancez sans ce paramètre. La commande en échec termine volontairement avec une erreur.
Gardez le fichier d’entrée immuable pendant cet essai. Pour tester une correction, créez un nouveau fichier et conservez l’ancien. L’empreinte identifie un contenu ; elle ne constitue pas à elle seule une sauvegarde de la source.
5. Connaître les limites avant de généraliser
Le programme travaille séquentiellement sur de petits snapshots complets. Il refuse les partitions vides, y compris une journée légitimement sans vente : en production, ce cas exige un signal explicite de complétude. Il ne gère ni delta, ni ordre des révisions concurrentes, ni dépendance entre plusieurs tables.
Deux exécutions portant des versions différentes peuvent écraser la même partition dans un ordre indésirable. Ajoutez une politique de sérialisation ou un contrôle de version adapté au stockage. Une transaction SQLite ne couvre pas non plus un appel à une API externe, un email ou un paiement. Pour ces effets, prévoyez un mécanisme d’idempotence propre au destinataire.
Choisir entre planificateur simple, Airflow et Dagster
Pour un traitement isolé, un planificateur simple peut rester adapté si l’équipe maîtrise verrouillage, historique, alertes et procédure de reprise. Son coût apparent augmente lorsque ces fonctions deviennent du code maison à maintenir.
Airflow mérite un test si votre besoin est d’expliciter des enchaînements de tâches et leurs exécutions historiques, notamment dans un parc qui l’utilise déjà. Dagster mérite un test si la lecture par actifs de données et partitions correspond mieux à votre exploitation. Ces repères sont des critères de décision, pas un classement des produits.
Comparez les options sur le même exercice : une source tardive, une tâche qui écrit puis perd sa confirmation, une correction historique et un consommateur bloqué jusqu’aux contrôles. Observez le temps de diagnostic, les manipulations nécessaires et les preuves accessibles à la personne d’astreinte.
Les documentations consultées affichent Airflow 3.3.2 et Dagster 1.13.25. Ce guide utilise leurs mécanismes documentés de reprise ; il ne dépend pas d’une preview. Le tutoriel reste indépendant de ces installations : il teste d’abord le contrat d’écriture que votre orchestrateur appellera.
Évaluer le coût d’exploitation et du backfill
L’atelier n’entraîne aucun appel facturé. Dans un système réel, comptez le calcul, le stockage, les journaux, les transferts et le temps de maintenance, même avec une orchestration auto-hébergée.
Pour donner un repère daté, la page Dagster+ affiche un plan Starter à 100 USD par mois, auquel s’ajoutent 0,035 USD par crédit et, en Serverless, 0,010 USD par minute de calcul. Les crédits additionnent les matérialisations d’actifs et les ops exécutées. Ce n’est donc pas un prix par pipeline. Pro est sur devis ; le mode Hybrid conserve vos coûts d’infrastructure. Vérifiez les options de résidence européenne et les conditions contractuelles selon votre besoin. Tarifs Dagster+ au 4 octobre 2026.
Avant un gros recalcul, mesurez une partition représentative, fixez une concurrence maximale et gardez une capacité disponible pour les flux du jour. Le retour publié par Dagster le 8 septembre sur un déploiement Kubernetes/Azure souligne justement que le nombre de runs ne décrit pas à lui seul la capacité consommée. Les formes de calcul diffèrent. Retour d’exploitation Dagster+ Hybrid.
Une procédure de reprise utilisable en astreinte
Préparez une fiche courte pour chaque pipeline critique :
- Périmètre : dates métier, source et version de code à rejouer.
- État : ce qui a été écrit, validé et effectivement livré aux consommateurs.
- Action : commande ou sélection de partitions, concurrence et limite de tentatives.
- Acceptation : clés uniques, totaux attendus, partitions voisines préservées et contrôles métier.
- Escalade : responsable, délai maximal de fraîcheur et condition d’arrêt du backfill.
Une erreur réseau temporaire peut justifier une reprise limitée. Une source invalide doit produire une alerte exploitable : recommencer la même lecture ne la corrigera pas. Si le programme disparaît brutalement, une tentative peut rester started ; elle doit être rapprochée de la partition réellement validée avant toute décision.
Le premier essai utile consiste à prendre un pipeline existant et à provoquer les deux pannes de l’atelier en environnement de test. Mesurez le délai de restauration, les interventions humaines et la conformité des résultats. Vous pourrez ensuite décider si le problème vient du code d’écriture, des contrôles ou de l’outillage d’orchestration.
Pour relier cette démarche à vos règles métier, poursuivez avec les contrats de données et les modèles sémantiques. Nymphar peut vous accompagner pour cadrer un premier pipeline et sa procédure de reprise.