Étude de cas · En production
Attribution concurrente d'identifiants
Plusieurs opérateurs créent des fiches en même temps, depuis des postes différents. Chacune doit recevoir un numéro unique et consécutif. Sans base de données, sans serveur de transactions : seulement des fichiers et un verrou.
- Rôle
- Conception, développement et déploiement — seul
- Durée
- Juillet 2026 — en service depuis
- Volume
- 1 966 lignes (PHP, Python, JavaScript)
- Données
- 3 943 fiches synchronisées depuis l'ERP
- Stack
- PHP 8 · Python 3 · JavaScript · SMTP
- Cœur du sujet
- Exclusion mutuelle et libération automatique des ressources
Le problème
Un « moyen de programme » est identifié par un numéro séquentiel. Quand un opérateur crée une fiche, l'application doit lui attribuer le prochain numéro libre. Les fiches existantes viennent de l'ERP ; les nouvelles n'y remontent qu'après validation, avec plusieurs heures de décalage.
Le numéro doit donc être réservé pendant que l'opérateur remplit le formulaire — sinon deux personnes qui ouvrent le formulaire en même temps repartent avec le même numéro, et la collision n'est découverte qu'à l'intégration dans l'ERP, bien trop tard pour être corrigée simplement.
La condition de course
L'approche naïve — lire le dernier numéro, ajouter un — échoue dès que deux requêtes s'intercalent. C'est le scénario que le système doit rendre impossible :
La solution : des baux à expiration
À l'ouverture du formulaire, le serveur ne se contente pas de calculer le prochain numéro : il le réserve dans un fichier de verrous, avec une date d'expiration à 15 secondes. Tant que ce bail est valide, aucun autre poste ne peut obtenir ce numéro.
La sélection parcourt les numéros croissants et retient le premier qui n'est ni déjà utilisé dans l'ERP, ni sous bail actif. L'opération complète — nettoyage des baux expirés, recherche, pose du nouveau bail — s'exécute à l'intérieur d'un unique verrou exclusif sur le fichier. Deux requêtes simultanées sont donc sérialisées : la seconde voit la réservation de la première.
Décisions techniques
Un bail à expiration, plutôt qu'un verrou explicite
Verrou libéré par le clientUn verrou que seul le client peut libérer est un verrou qui finit bloqué : onglet fermé, navigateur planté, poste éteint, coupure réseau. Le numéro serait alors perdu définitivement.
Avec un bail daté, l'absence de nouvelle est un cas normal, pas une panne. Le nettoyage n'a besoin d'aucune tâche de fond : toute requête qui consulte le fichier purge au passage les baux périmés. Le système se répare tout seul.
15 secondes, renouvelées tant que le formulaire est ouvert
Bail long (5 minutes)La durée arbitre entre deux gênes. Trop court, le numéro est repris sous les doigts d'un opérateur qui réfléchit. Trop long, un formulaire abandonné gèle un numéro pendant des minutes, et l'opérateur suivant voit un trou inexpliqué dans la numérotation.
15 secondes avec renouvellement périodique donne le meilleur des deux : un formulaire réellement ouvert conserve son numéro indéfiniment, un formulaire abandonné le rend en quelques secondes.
Toute écriture passe par une fonction de mutation sous verrou
Lire, modifier, réécrire à chaque appelLe fichier de verrous est modifié depuis cinq endroits différents. Chacun appelle le même helper, qui prend une fonction transformant l'état et garantit que lecture et écriture ont lieu dans le même verrou. Sans cette factorisation, il suffirait qu'un seul appelant relise le fichier hors du verrou pour rouvrir la condition de course — et ce serait invisible en relecture de code.
Difficultés rencontrées
Le bail peut expirer pendant la saisie
Un opérateur peut laisser le formulaire ouvert et partir. À la validation, le bail posé à l'ouverture a pu expirer — et être repris par quelqu'un d'autre. Valider aveuglément réintroduirait exactement la collision que le système est censé empêcher.
La validation revérifie donc la disponibilité du numéro au moment de l'écriture, sous verrou, plutôt que de faire confiance à la réservation initiale. La réservation est une optimisation du confort ; la garantie, elle, est posée à l'écriture.
Libérer le numéro quand l'utilisateur renonce
Fermer le formulaire sans valider devait rendre le numéro immédiatement, et non attendre l'expiration : sinon un opérateur qui hésite crée des trous visibles dans la numérotation. Chaque chemin de sortie — bouton « Annuler », clic en dehors, touche d'échappement — déclenche une libération explicite. L'expiration reste le filet de sécurité pour les cas qu'on ne contrôle pas.
Résultats
3 943
fiches synchronisées depuis l'ERP
0
collision de numéro constatée
15 s
durée d'un bail, renouvelable
0
serveur de base de données
L'application tourne depuis juillet 2026 sur le réseau de l'atelier. Chaque création
déclenche un e-mail au responsable, dont chaque étape — connexion, STARTTLS,
authentification, envoi — est tracée dans un journal quotidien : en cas d'échec,
on sait immédiatement où ça a cassé, sans reproduire le problème.
Ce que je referais autrement
Le renouvellement du bail dépend du navigateur. Si l'onglet est mis en arrière-plan, le navigateur peut ralentir les minuteurs et laisser le bail expirer alors que l'utilisateur est toujours là. La revérification à l'écriture évite la collision, mais l'opérateur peut voir son numéro changer. Utiliser l'API de visibilité de page pour reprendre le renouvellement au retour au premier plan corrigerait ce cas.
Aucune authentification. C'est un choix assumé — le service est confiné au réseau local et la règle de pare-feu est limitée au profil privé — mais cela signifie qu'aucune action n'est attribuable à une personne. Pour un outil qui déclenche des e-mails au nom de l'entreprise, une identification même minimale serait plus saine.