🍪🚦Sidekiq et les signaux, tout savoir et éviter les problèmes
(Temps de lecture : 5 minutes)
Dans une précédente newsletter, Ismaël vous expliquait que Sidekiq était très utile pour décharger le serveur applicatif de toutes les tâches qui ne nécessitent pas de retour immédiat à l'utilisateur (envoi de mail, changement d'état, traitement de hooks, etc...).
L'utilisation d'un outil comme Sidekiq, de manière aussi massive et centrale dans nos apps nous oblige à bien connaître son fonctionnement.
Aujourd'hui, nous allons faire un focus sur les “signaux”, comment Sidekiq les interprète et je vous présenterai un cas pouvant provoquer des erreurs très (très très comme l'âne trotro) problématiques et comment l'éviter.
Au programme aujourd’hui :
Temps de lecture : 5 minutes
Hello les petits Biscuits !
Bienvenue sur la 19ème édition de Ruby Biscuit.
Vous êtes maintenant 445 abonnés 🥳
Voici 2 annonces qui pourraient vous intéresser pour rentabiliser votre 22 mars 😉 :
Le Wagon Paris organise un salon du recrutement qui aura lieu dans deux semaines, le vendredi 22 mars. Si vous êtes recruteur, à la recherche de profils tech (dev junior, data et product) pour agrandir vos équipes vous pouvez vous y inscrire ici !
React Paris : La Conférence Incontournable sur les dernières avancées de React ! Assistez à la conférence sur React Paris, un événement incontournable sur Paris et en ligne le 22 mars prochain ! Au programme : les toutes dernières avancées de l'écosystème React avec des présentations captivantes sur les React Server Components, l'intelligence artificielle, l'accessibilité, le design, les performances, Remix, TypeScript, et bien plus encore ! Ne manquez pas cette opportunité d'apprendre et d'échanger avec des experts, des auteurs et des membres clés de l'équipe, ainsi qu'une communauté dynamique de développeurs. Vous pouvez réservez votre place pour cette journée exceptionnelle sur https://react.paris !
Avant de vous laisser entre les mains de Quentin pour l’article du mois, je tenais à vous rappeler que vous êtes tous les bienvenus pour donner votre avis en commentaire et partager vos expériences sur les sujets que nous abordons. Vous pouvez aussi mettre un petit like ❤️ et/ou partager la newsletter à un copain ou une copine ! 😉
Bonne lecture.
Sidekiq et les signaux, tout savoir et éviter les problèmes
Commençons par un petit glossaire pour partir ensemble sur de bonnes bases :
Ici je me contente de reprendre des définitions d'internet ainsi que les liens pour aller plus loin.
Signal : Forme de communication entre processus utilisé par les systèmes de type Unix et ceux respectant les standards POSIX. Il s'agit d'une notification asynchrone envoyée à un processus pour lui signaler l'apparition d'un événement
TL;DR Ctrl-c dans le terminal execute le signal SIGINT sur votre programme
https://fr.wikipedia.org/wiki/Signal_(informatique)
Graceful stop : Méthode d'arrêt d'un programme permettant au dit programme d'effectuer les tâches en cours sans en accepter de nouvelles
Idempotence : signifie qu'une opération a le même effet qu'on l'applique une ou plusieurs fois
https://fr.wikipedia.org/wiki/Idempotence
Sidekiq et les signaux
Sidekiq est un processus indépendant de votre serveur rails. Il est lancé généralement avec la commande
bundle exec sidekiq -C config/sidekiq.yml # + des options si besoin
Afin d'avoir une gestion fine de son fonctionnement, Sidekiq implémente certains signaux pour permettre le gracefull stop
.
La liste détaillée se trouve ici et aujourd’hui nous allons nous intéresser plus particulièrement à TSTP
et TERM
. Sidekiq implémente également le signal TTIN
mais il n'est utile que pour du debug.
TSTP :
Signal qui ordonne à Sidekiq de ne plus accepter aucun job. Vos jobs resteront donc dans la queue Redis en attendant qu'un nouveau processus soit démarré. Le processus Sidekiq sera lui marqué comme étant quiet
.
TERM :
Signal qui ordonne à Sidekiq de s'arrêter sous un certain délai (25 secondes par défaut, configurable avec l'option -t
). Sous le manteau cette action entraîne immédiatement le passage du processus en quiet
tout comme le fait le signal TSTP
.
Passé le délai, tout job non terminé sera arrêté immédiatement quelque soit l'action en cours et c'est là que les problèmes peuvent arriver 😱 .
Le danger, je me ris du danger 🦁
L'idéal est d'avoir des jobs courts et idempotent et c'est aussi ce que Sidekiq recommande dans ses bonnes pratiques.
Dans le cas d'un job qu'on ne voudrait pas découper, il est important de connaître les limites et les moyens de se protéger.
Exemple d'un job en danger
Parce qu'un exemple vaut 1000 explications, effectuez les étapes suivantes :
Copiez le code du job ci dessous dans le dossier adéquat de votre application
Lancez dans votre terminal
bundle exec sidekiq -C config/sidekiq.yml -t
Dans la console rails de votre application, faites :
LongRunningNotSafeJob.perform_async
Dans la fenêtre ou s'éxecute sidekiq, faites
Ctrl-c
Observez le résultat
Répétez l'opération plusieurs fois et voyez ou le programme s'arrête. Normalement ce n'est jamais au même endroit.
# app/jobs/long_running_not_safe_job.rb
class LongRunningNotSafeJob
include Sidekiq::Job
def perform(init_index=1)
puts "I am entering in a long running worker"
(init_index..20).each do |i|
puts "Doing a payment for index #{i}"
sleep(1)
puts "Saving payment for index #{i} in a database record"
end
puts "I am exiting from a long running worker"
end
end
À chaque fois que Sidekiq s'arrêtera, il remettra ce job dans la queue qui reprendra à 1.
Pour prendre un exemple de la vraie vie qui pourrait poser problème, prenons le cas d'un call API sur une resource create
. Je demande à mon API foo
de me créer une ressource bar
. Une fois l'opération réussie, l'API doit me retourner l'ID de foo
que je stocke pour pouvoir travailler dessus par la suite. Si mon job Sidekiq s'arrête juste après l'appel API mais avant que j'ai enregistré l'ID, je me retrouve avec un foo
fantôme qui hantera mon application lorsque je devrai faire du débogage.
Cela peut vite s'avérer très sensible lorsque l'on parle d'opérations de paiements.
Comment éviter cela
Respecter les bonnes pratiques de Sidekiq ⬆️
Protéger les jobs longs en ayant en tête qu'ils peuvent s'arrêter à tout moment après un délai de 25 secondes. Dans l'exemple ci dessous après chaque tour de boucle, le job va vérifier s'il y a un processus Sidekiq ayant reçu l'ordre de s'arrêter (
quiet
) et que le job est en train d'être exécuté par ce processus. Si c'est le cas, le job va se renvoyer dans la queue - avec un paramètre lui permettant de reprendre là où il en était - et sortir de la boucle à l'aide dubreak
. Ainsi, lorsqu'un nouveau processus sera allumé, le job recommencera son travail.
# app/jobs/long_running_safe_job.rb
class LongRunningSafeJob
include Sidekiq::Job
def perform(init_index=20)
puts "I am entering in a long running worker"
(init_index..20).each do |i|
puts "Doing a payment for index #{i}"
sleep(1)
puts "Saving payment for index #{i} in a database record"
# Sidekiq let 25 seconds to finish running workers when it receive a signal to stop or restart
# Quitting here when then process is quiet avoids losing important informations during the loop.
if Sidekiq::ProcessSet.new.any? { |p| p["pid"] == Process.pid && p["quiet"] == "true" }
puts "SidekiqProcess is terminating. Gracefully exiting ..."
# Reschedule job so it can be reruned safely later
LongRunningSafeWorker.perform_async(i + 1)
break
end
end
puts "I am exiting from a long running worker"
end
end
Maintenant que vous êtes prévenus, soyez vigilants aux signaux 😘
Pour aller plus loin, voici un article très bien fait - publié également dans le Ruby Weekly de cette semaine - qui explique en profondeur le fonctionnement de Sidekiq : https://www.mikeperham.com/how-sidekiq-works/
And thanks for the fish
— Quentin
L’agence de recrutement pour les leads dévs RoR !
Comme vous le savez, derrière Ruby Biscuit, il y a Capsens 👋 , nous sommes une agence web qui fait du Ruby on Rails depuis 10 ans.
Avec le temps on s'est rendu compte que beaucoup de dévs choisissent leur entreprise un peu par hasard alors qu'ils pourraient davantage s'épanouir et se valoriser dans des structures qui leur correspondent mieux. De plus on sait à quel point les process de recrutement peuvent ne pas être adaptés à notre métier et nos profils.
Ce qui tombe super bien c'est que chez Capsens nous avons une excellente connaissance de l'écosystème RoR en France, avec un réseau d'entreprises considérable. La plupart étant des boites bien installées (+ de 5 ans), avec des équipes tech déjà présentes et qui recherchent avant tout des leads dévs et dévs séniors.
C'est pourquoi nous avons décidé de mettre à profit nos ressources pour vous aider à trouver le poste de vos rêves !
Alors tu as plusieurs années d’expériences ? Tu souhaites trouver le prochain poste de lead dév de tes rêves ?
Concrètement voilà ce qui va se passer :
Réponds à cette newsletter en te présentant en deux lignes !
Je t’envoie aussitôt notre test technique pour évaluer ta séniorité
Je te propose des créneaux pour un appel afin de faire ta connaissance et que tu me dises ce que tu cherches pour t’épanouir dans une entreprise.
Je te propose 3 entreprises qui correspondent à ton profil et tes aspirations. Pour chacune de ces entreprises :
Je me charge de te donner un max d’infos et répondre à toutes tes questions par message (horaires, ambiance, taille et séniorité de l’équipe, responsabilités, marge de manœuvre pour la négociation du salaire, localisation des bureaux, politique de télétravail, etc). Pas d’appels inutiles.
Avant de rencontrer le recruteur lui-même, je te mets en relation avec un développeur de leur équipe. Tu pourras alors te faire une idée de comment ça se passe de l’intérieur.
Enfin, le recruteur te recevra ! Il aura déjà eu toutes les informations que je lui aurai transmises sur toi ce qui vous permettra d’aller à l’essentiel !
Lance-toi, on attend ton e-mail ! Et si tu aimes déjà ton travail, ne nous contacte surtout pas ! Ou alors fais-le pour nous recommander ta boîte 😉
Mélanie
🤸🏻♂️