Concept : Cycle de Mise à Jour & Auto-Mise à Jour Sans Verrouillage (Zero-Lock Update)
Navigation : Documentation > Concepts > Cycle de Mise à Jour
Composants associés : Moteur Central (core-engine) | Trampolines Rust
Sommaire
- Introduction & Problématique sous Windows
- L'Architecture de Découplage Érable (Pointeur vs Payload)
- 2.1 Les Trois Piliers du Découplage
- Cycle de Mise à Jour d'une Application Standard
- Cycle d'Auto-Mise à Jour du Moteur Érable (Self-Update)
- 4.1 Déroulement Pas-à-Pas de l'Auto-Mise à Jour
- Mise à Jour du Binaire Trampoline Rust (
erable update-trampolines) - 5.1 La Technique du Renommage Différé Windows
- Capacités de Rollback Atomique & Zéro Interruption
- Matrice Comparative : Érable vs Gestionnaires Traditionnels
1. Introduction & Problématique sous Windows
Dans les systèmes d'exploitation modernes, et tout particulièrement sous Microsoft Windows, la mise à jour d'un exécutable en cours de fonctionnement constitue un défi technique majeur :
- Le Verrouillage Exclusif (
ERROR_SHARING_VIOLATION/0x20) : Lorsqu'un binaire.exeou une bibliothèque.dllest exécuté sous Windows, le sous-système de mémoire virtuelle et le gestionnaire de cache système placent un verrou d'exécution partagé qui interdit formellement toute écriture ou suppression directe du fichier sur disque. - La Défaillance des Gestionnaires Traditionnels : Les gestionnaires de paquets classiques (Chocolatey, Scoop, WinGet) échouent régulièrement lors de l'auto-mise à jour ou de la mise à niveau d'outils d'arrière-plan (terminaux, démons, shells) :
- Soit ils exigent la fermeture préalable de toutes les fenêtres de terminal ;
- Soit ils recourent à des scripts PowerShell temporaires hors processus qui échouent silencieusement ;
- Soit ils laissent le système dans un état corrompu à mi-parcours (half-installed state).
Érable a été conçu pour éliminer structurellement ce problème grâce à une architecture sans état (stateless) reposant sur le découplage strict entre Trampoline, Pointeur Atomique et Payload Immuable.
2. L'Architecture de Découplage Érable (Pointeur vs Payload)
Sur le poste client, l'exécution d'un logiciel via Érable repose sur une chaîne d'indirection à trois niveaux :
Shell Utilisateur (Terminal)
│
▼ (1. Appel du binaire dans le PATH)
~/.erable/bin/<nom>.exe (Trampoline Rust Universel, ~80 Ko)
│
▼ (2. Lecture éphémère du fichier texte)
~/.erable/bin/<nom>.exe.target (Pointeur texte : "packages/<nom>/current/<cible>")
│
▼ (3. Exécution transparente du processus cible)
~/.erable/packages/<nom>/<version>/<cible> (Payload binaire immuable)
2.1 Les 3 Piliers du Découplage
- Le Trampoline (
bin/<nom>.exe) : Binaire Rust autonome unique dupliqué pour chaque alias de commande. Il ne contient aucune logique métier : son seul rôle est de lire le fichier.targetadjacent et de lancer le processus réel avec substitution d'arguments. - Le Pointeur Atomique (
bin/<nom>.exe.target) : Fichier texte ultra-léger contenant le chemin relatif ou absolu du binaire cible. Le trampoline l'ouvre, lit sa ligne unique en mémoire en moins de 1 milliseconde, puis referme immédiatement le descripteur de fichier avant d'exécuter la commande. Le pointeur n'est donc jamais maintenu ouvert ni verrouillé. - Le Répertoire Immuable (
packages/<nom>/<version>/) : Chaque version possède son propre sous-dossier figé. Une version en cours d'utilisation par un processus actif n'est jamais altérée.
3. Cycle de Mise à Jour d'une Application Standard
Lors de la mise à niveau d'un paquet logiciel (ex. erable install ripgrep vers une nouvelle version) :
sequenceDiagram
participant User as Utilisateur / CI
participant Engine as Moteur Érable
participant Store as packages/<pkg>/
participant Ptr as bin/<pkg>.target
User->>Engine: erable install ripgrep (nouvelle version)
Engine->>Store: Téléchargement & Extraction dans packages/ripgrep/14.2.0/
Note over Store: Le processus ripgrep 14.1.0 peut tourner sans gêne
Engine->>Store: Mise à jour du lien/dossier packages/ripgrep/current
Engine->>Ptr: Écriture atomique du nouveau chemin dans ripgrep.exe.target
Engine-->>User: Mise à jour terminée sans interruption !
- Extraction Parallèle : La nouvelle version (
14.2.0) est décompressée dans un répertoire hermétique flambant neufpackages/ripgrep/14.2.0/. Même si l'ancienne version14.1.0est actuellement en cours d'exécution dans un terminal actif, aucun fichier de14.1.0n'est touché. - Bascule Atomique : Le pointeur
packages/ripgrep/currentet le fichierbin/ripgrep.exe.targetsont réécrits de manière atomique (écriture dans un fichier.tmppuis renommage atomique via l'API de l'OS). - Effet Immédiat : Toute nouvelle exécution de
rginvoque instantanément la version14.2.0, tandis que les processus14.1.0déjà démarrés continuent de s'exécuter jusqu'à leur terminaison normale sans incident.
4. Cycle d'Auto-Mise à Jour du Moteur Érable (Self-Update)
Le moteur central Érable lui-même est géré selon les mêmes principes que n'importe quel paquet du catalogue :
~/.erable/
├── bin/
│ ├── erable.exe # Trampoline vers le moteur
│ └── erable.exe.target # Contient : "core/engine/erable.nu"
└── core/
├── engine/ # Moteur Nushell modulaire actif
└── versions/ # Historique des versions du moteur
4.1 Déroulement Pas-à-Pas de l'Auto-Mise à Jour
Lorsque la commande d'auto-mise à jour est déclenchée :
- Invocateur : L'utilisateur lance
erable updateouerable install erable. Le trampolinebin/erable(.exesous Windows) démarrenuavec le script actif pointé par.target. - Téléchargement Hors-Flux : Le nouveau moteur Érable est téléchargé et vérifié cryptographiquement (SHA-256) dans un dossier hermétique
packages/erable/<version>/(oucore/engine.new/). - Absence Totale de Verrou sur les Scripts : Contrairement aux binaires compilés exclusifs, les scripts d'interprétation sont chargés en mémoire. De surcroît, le nouveau code est déposé dans une arborescence dédiée sans jamais altérer l'existant.
-
Permutation Pivot Universelle (Harmonisée Linux / macOS / Windows) : La stratégie de bascule est strictement identique sur tous les systèmes d'exploitation, garantissant une portabilité 100 % homogène :
-
Temps 1 (
current -> current.old) : Le dossier actif en cours d'utilisation est renommé encurrent.old. Sous Windows (NTFS) comme sous Linux/macOS (POSIX), le renommage d'un répertoire contenant des fichiers en lecture est parfaitement légal et garanti sans erreurERROR_SHARING_VIOLATION. - Temps 2 (
new -> current) : Le nouveau dossier de version est positionné à l'emplacement standardcurrent(oucore/engine). - Temps 3 (Bascule du pointeur) : Le fichier pointeur
bin/erable[.exe].targetest réécrit de manière atomique pour cibler le nouveau scripterable.nu. - Temps 4 (Nettoyage différé) : Le dossier
current.oldest supprimé de manière asynchrone dès que les descripteurs ouverts sont relâchés. - Résultat : La session terminal reste intacte et la commande suivante invoque instantanément le nouveau moteur.
5. Mise à Jour du Binaire Trampoline Rust (erable update-trampolines)
Que se passe-t-il lorsque le binaire trampoline.exe lui-même fait l'objet d'une mise à jour (optimisation de latence, support d'un nouveau protocole OS) ?
5.1 La Technique du Renommage Différé Windows (Safe Rename Pattern)
Sous Windows, le système d'exploitation interdit l'écrasement ou la suppression d'un binaire en cours d'exécution, mais il autorise son renommage :
flowchart LR
A["bin/erable.exe (Verrouillé en exécution)"] -->|1. Renommage légal| B["bin/erable.exe.old (Toujours verrouillé)"]
C["tools/trampoline.exe (Nouveau binaire)"] -->|2. Copie vers l'emplacement libéré| D["bin/erable.exe (Actif pour les futurs appels)"]
B -->|3. Nettoyage différé| E["Suppression post-exécution ou au redémarrage"]
- Renommage du Trampoline Actif : Le moteur renomme
bin/erable.exeenbin/erable.exe.old. Windows accepte l'opération sans lever d'ERROR_SHARING_VIOLATION. - Copie du Nouveau Binaire : L'emplacement d'origine
bin/erable.exeétant désormais vacant, la nouvelle version du trampoline y est immédiatement copiée depuistools/trampoline.exe. - Mise à Jour de l'Empreinte : Le fichier
tools/trampoline.hashest mis à jour avec le nouveau SHA-256 source. - Purge du Fichier Ancien : Le fichier
.oldest programmé pour suppression automatique dès que le dernier descripteur de processus est relâché.
6. Capacités de Rollback Atomique & Zéro Interruption
L'architecture sans état d'Érable confère une sécurité opérationnelle inégalée :
- Rollback en $O(1)$ : Si une nouvelle version d'un outil s'avère instable, le retour arrière ne nécessite aucun re-téléchargement ni réinstallation. Il suffit de modifier le pointeur
.targetpour pointer à nouveau vers le sous-dossier de la version précédente (packages/<nom>/<version_anterieure>/). - Isolation Totale des Dépendances Runtimes : Les dépendances partagées (ex.
7zip) sont installées dans leur propre store versionné indépendant. La mise à jour d'une dépendance ne modifie jamais les binaires des applications consommatrices. - Préservation des Données Utilisateur : Les données applicatives continuent d'être stockées dans
%APPDATA%,%LOCALAPPDATA%ou~/.config. Les cycles de mise à jour d'Érable n'interfèrent jamais avec les fichiers de configuration utilisateur.
7. Matrice Comparative : Érable vs Gestionnaires Traditionnels
| Critère | Érable | Scoop | Chocolatey | WinGet |
|---|---|---|---|---|
Verrouillage de binaire sous Windows (0x20) |
🟢 Zéro Verrou (Découplage .target) |
🟡 Fréquent sur les shims actifs | 🔴 Blocage systématique sur les fichiers ouverts | 🔴 Erreur fréquente (InUse) |
| Auto-mise à jour du gestionnaire en session | 🟢 100 % Transparent & Atomique | 🟡 Nécessite scoop update séparé |
🔴 Nécessite élévation UAC & redémarrage | 🔴 Géré par le Windows Store |
| Mise à jour d'un logiciel en cours d'exécution | 🟢 Succès immédiat (Nouvelle version active au prochain appel) | 🔴 Échec (cannot rename directory in use) |
🔴 Échec de l'installeur MSI / InnoSetup | 🔴 Échec du programme d'installation |
| Temps de bascule de version | 🟢 < 2 ms (Réécriture atomique .target) |
🟡 500 ms à 2 s (Recréation des shims) | 🔴 Plusieurs secondes / minutes (Désinstallation complète) | 🔴 Réinstallation complète |
| Rollback instantané sans réseau | 🟢 Natif (Historique immuable conservé) | 🟡 Manuel (scoop reset) |
🔴 Impossible sans re-téléchargement | 🔴 Impossible |
| Nécessité de privilèges Administrateur (UAC) | 🟢 Jamais (100 % User-Space) | 🟢 Rarement (hors bucket nonportable) |
🔴 Obligatoire | 🟡 Requis pour la majorité des packages |