Sweetohm

Michel Casabianca


Lors de mes derniers développements, j’ai eu besoin de garantir que deux publications ne pouvaient être lancées simultanément sur la chaîne des ouvrages Dalloz.

La méthode traditionnelle consiste à écrire un fichier de lock. Au lancement de la publication, on vérifie que le fichier n’est pas déjà présent. S’il ne l’est pas, on le crée et on continue, puis on l’efface à la fin du traitement. S’il l’est, on arrête en erreur car une autre publication est en cours.

Cette méthode est simple, mais malheureusement, elle est fausse. Pour au moins deux raisons :

  • Entre le temps où l’on vérifie si le fichier existe et où on le crée, une autre vérification peut être faite. On a alors deux publications en même temps.
  • Si le processus de publication plante, le fichier de lock n’est jamais effacé et plus aucune publication n’est possible.

Dans un précédent poste, j’ai décrit une méthode d’exclusion qui fonctionne : elle consiste à ouvrir un port en écoute. Si le port n’est pas déjà ouvert, alors le processus peut continuer, sinon il est interrompu.

Cette méthode adresse les deux objections précédentes : on évite le problème de simultanéité du test et lorsque le processus est arrêté, le port est libéré par le système d’exploitation.

Cependant, cette méthode ne fonctionne que dans un programme. Comment faire pour protéger l’exécution concurrente d’un script shell par exemple ?

Pour résoudre cette question, j’ai écrit une commande que j’ai appelée single. On la lance en lui passant le port de lock et la commande a exécuter. Par exemple :

$ single 12345 build code-travail

Elle commence par ouvrir le port en écoute (ici le 12345), puis, s’il est libre, elle lance la commande (à savoir build code-travail). Lorsque la commande se termine, le port est libéré.

Ceci permet de lancer de manière exclusive toute commande, mais aussi des commandes différentes. Par exemple, elle permet d’interdire le mise à jour de la chaîne de publication alors qu’une publication est en cours (et inversement).

Le projet de cette commande est Open Source (sous licence Apache) et est accessible sur Github. Des versions binaires sont disponibles pour la plupart des OS.

Enjoy!