Uploads résumables & throttling up Décidé
La reprise après coupure est un sous-produit de la dédup — pas de sessions d'upload, pas d'état de reprise : un re-run idempotent suffit. Reste à cadrer le pipeline, le throttling et la discipline de retry.
Le problème
Le premier backup est long — bien plus long que l’intuition ne le dit.
Sur ces durées, les coupures ne sont pas l’exception mais la règle : réseau qui tombe, laptop qui s’endort, box qui redémarre. Si chaque incident renvoie à zéro, le backup initial ne se termine jamais — la spirale de la mort des gros premiers backups. Et à l’inverse, un backup qui sature le lien du bureau à 14 h se fait désinstaller.
Ce que l’architecture donne déjà
- La reprise est un sous-produit de la dédup. L'unité d'upload est le chunk. Après une coupure, le client relance le même backup : le scan repasse en quelques minutes, les fichiers changés sont re-chunkés localement, et le check d'existence répond « déjà là » pour tout ce qui était monté avant la coupure → seul le reste part. Les 400 Go déjà uploadés sont acquis, sans état de reprise ni protocole spécial.
- Rien de visible avant la fin. Construction en post-order → la racine du snapshot est écrite en dernier. Backup interrompu = des chunks orphelins en attente (protégés du GC par les époques), aucun snapshot partiel, jamais. Un snapshot existe entièrement ou pas du tout.
Décision 1 — Reprise par dédup, pas de sessions d’upload
On n’introduit pas de protocole d’upload résumable avec état (sessions multipart façon S3, identifiants qui expirent, nettoyage de sessions mortes). La reprise, c’est un re-run idempotent + les checks d’existence — le mécanisme existe déjà, il est correct par construction, et il n’y a rien à synchroniser ni à faire expirer.
Corollaire assumé : pas de reprise intra-chunk. Un chunk de 8 Mio interrompu en vol se renvoie en entier — quelques secondes perdues, contre une vraie complexité de protocole. La seule notion de « session » vit côté serveur : l’époque GC qui protège les chunks fraîchement arrivés tant qu’aucune racine ne les référence (le point ouvert de la section C).
Décision 2 — Le coût de reprise assumé : re-chunker localement
Reprendre exige de relire et re-chunker les fichiers changés pour recalculer leurs adresses — il n’y a pas d’état local, c’est le contrat stateless. On l’assume : le disque local est des ordres de grandeur plus rapide que le WAN. Re-chunker 2 To ≈ 2–3 h de lecture locale, contre des jours de WAN économisés par la dédup.
Le cas pathologique — l’image VM géante interrompue cinq fois — a sa vraie réponse ailleurs : le CBT de la section P, qui ne relit que les blocs modifiés. Pas un mécanisme de checkpoint qui violerait le contrat stateless. Le cache éphémère peut mémoriser la progression — optionnel et jetable, comme toujours.
Décision 3 — Le pipeline d’upload
# fenêtre en vol bornée (RAM NAS) · N petit par défaut · ack = contrat « durable avant visible »
Les checks d’existence partent par lots de centaines d’adresses — la forme exacte de l’API est le point ouvert de la section B, le client est déjà conçu pour le batch. L’ack serveur suit le contrat de durabilité : ce qui est acquitté est sur disque.
Décision 4 — Throttling : token-bucket + plages horaires
Limites montée/descente configurables, avec un planning (ex. 10 Mbit/s de 8 h à 19 h, illimité la nuit), implémentées en token-bucket côté client sur les flux d’upload. Le throttling adaptatif (céder la place quand le réseau est occupé) est noté pour plus tard — le planning couvre l’essentiel du besoin réel. Le rate-limiting côté serveur (quotas, protection d’abus) est un sujet distinct de la section B.
Décision 5 — Discipline de retry
- Backoff exponentiel + jitter, par chunk — les échecs transitoires (réseau, 5xx) se retentent tout seuls.
- Transitoire ≠ fatal — erreur d'authentification ou quota dépassé : arrêt franc avec diagnostic, pas une boucle de retry qui masque le problème.
- Réveil de laptop = simple continuation — rien à faire.
- Coupure longue — le run échoue proprement après une deadline, et le run planifié suivant est la reprise : même commande, pas de « mode reprise ». La dédup fait le reste.