Comment garantir l'unicité d'un traitement

Voici une technique pour lancer un traitement automatisé une seule et unique fois sur un environnement.

Un jour on vous parlera de notre utilitaire Combawa qui nous permet de piloter la reconstruction d'un site Drupal - que ce soit en local ou sur les serveurs (de test, de production)-.

Ce que je voulais vous partager pour cette fois c'est une technique que nous utilisons pour jouer des instructions une seule fois. Nous avons les hook_update_N() et hook_post_update_NAME() à disposition lorsqu'il s'agit de travailler sur la base de données ou à plus haut niveau. Imaginez maintenant devoir faire des actions sur votre serveur telles qu'ajouter un cœur à Solr, vider des indexes, modifier une cron. Des actions facilement scriptables, pas forcément liées à Drupal et à garantir qu'elles ne seront jouées qu'une seule fois.

Pour y parvenir, voici le squelette d'un patron :

  • Lever un drapeau dans un hook_post_update_NAME(),
  • Faire le traitement unique,
  • Mettre à jour la valeur du drapeau pour indiquer qu'il a été pris en compte.

Voici le code pour lever le drapeau.

/**
 * Raise a flag to reindex process.
 */
function project_post_update_1002(&$sandbox) {
  \Drupal::state('site_updates')->set('update_1002_reindexation_processed', 0);
}

Maintenant dans mon script de déploiement qui lance mes mises à jour, je dois évaluer la valeur de ce drapeau et s'il n'a jamais été joué, lancer les traitements associés.

Voici le code que nous exécutons, à vous de voir où le mettre dans le contexte de votre projet.

$DRUSH=./vendor/bin/drush
# Récupérer la valeur du drapeau
UPDATE_PROCESSED=$($DRUSH eval "print (int) \Drupal::state('site_updates')->get('update_1002_reindexation_processed', 0);")
if [[ $UPDATE_PROCESSED == 0 ]]; then
  $DRUSH search-api:clear global
  $DRUSH search-api:clear mag_authors
  $DRUSH search-api:index global
  $DRUSH search-api:index mag_authors
  # On n'oublie pas de modifier la valeur une fois les traitements lancés !
  $DRUSH eval "\Drupal::state('site_updates')->set('update_1002_reindexation_processed', 1)"
fi

Si vous aimez les frissons, vous pourriez aussi ne pas lever le drapeau dans le hook_post_update_NAME() et simplement vous fier au fait que \Drupal::state()->get() utilise le deuxième argument comme valeur par défaut.

Votre commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
Votre adresse servira à afficher un Gravatar et à vous notifier des réponses. Votre commentaire sera anonymisé si ce billet est dépublié pendant plus de 3 mois.
Pour lutter contre le spam notre système enregistre votre adresse IP et votre adresse e-mail si vous la partagez.
Nous vous invitons à consulter notre politique de confidentialité pour comprendre les traitements faits de ces données et comment les rectifier.

À propos de Julien

Co-fondateur - Scrum master & Expert technique

Utilisateur de Drupal depuis 2008, j’ai fait mes armes comme développeur chez Commerce Guys puis me suis mis à encadrer les nouveaux arrivants avant de donner des formations, participer aux avant ventes et accompagner les équipes au passage à Scrum.

Je suis impliqué dans la communauté française de Drupal depuis 2009, j’ai été tour à tour président puis vice-président de l’association Drupal France et francophonie entre 2011 et 2013.