Cloud : Traitements asynchrones sur le Cloud avec Sidekiq

Cloud 22 juin 2025

Au programme

 Nous allons construire une application basique avec Sidekiq afin de lancer un scheduler nous permettant de réaliser une tache simple, à savoir : récupérer la date et l'heure actuelle toutes les minutes. 

En local pour commencer

Vous pouvez récupérer le code ci-dessous sur GitHub au lien suivant :

GitHub - CamillePaquet/sidekiq_sample
Contribute to CamillePaquet/sidekiq_sample development by creating an account on GitHub.

Construction du squelette de l'application avec le lancement de Sidekiq

Dans ce tutoriel je vais utiliser VSCode en éditeur sur un environnement Linux Ubuntu (VM,WSL,multipass,serveur ou workstation)

  • Créez votre répertoire projet et ouvrez le sur VSCode
  • Création du fichier Gemfile et ajout des dépendances 
source 'https://rubygems.org'  
gem 'carioca', '~> 2.0'  
gem 'sidekiq', '~> 6.4.1'  
gem 'sidekiq-cron', '~> 1.2'  
gem 'redis', '~>4.6'  

 

    • sidekiq : lancement de taches de fond
    • sidekiq-cron : scheduler
    • redis : stockage des jobs
    • carioca : conteneur et registre avec inversion de contrôle pour vos applications

Voir :

GitHub - Ultragreen/carioca: Carioca : Configuration Agent and Registry with Inversion Of Control for your Applications
Carioca : Configuration Agent and Registry with Inversion Of Control for your Applications - Ultragreen/carioca
  • Création des dossiers config, helpers, workers, lib
    • config : Contient la configuration de l'application
    • helpers : Contient des méthodes utiles
    • workers : Contient les workers à lancer par les différents jobs.
  • Dans le dossier config créez un fichier init.rb
Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each { |file| require file unless File.basename(file) == 'init.rb' }  
  
def get_config  
  ApplicationController.configuration.settings  
end  
  
  
Sidekiq.configure_server do |config|  
  config.redis = { url: get_config.backend.redis.jobs.url.to_s }  
end  
  
Sidekiq.configure_client do |config|  
  config.redis = { url: get_config.backend.redis.jobs.url.to_s }  
end

  

  • Dans les dossiers helpers, workers et lib ajouter un fichier "init.rb" qui importera tous les fichiers du dossier

 

Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each { |file| require file unless File.basename(file) == 'init.rb' }  

Création du fichier config.ru pour le lancement de l'application :
 

require 'sidekiq'
require 'sidekiq/web'  
require 'sidekiq/cron/web'  
  
require_relative 'runner'  
require_relative 'config/init'  
  
secret_key = SecureRandom.hex(32)  
use Rack::Session::Cookie, secret: secret_key, same_site: true, max_age: 86400  
run Sidekiq::Web  

Ligne 2 et 3 : "sidekiq/web" et "sidekiq/cron/web" permettent de lancer l'interface web de sidekiq

    • Ligne 8 et 9 : création d'une session
    • Ligne 10 : lancement de l'application

 

  • Création du fichier de configuration config/settings.yml :
:runner:    
  :default:  
    :backend:  
      :redis:  
        :jobs:  
          :url: redis://localhost:6379/1  
  
  :development:  
    :application:  
      :name: Tutoriel Sidekiq  

Création du fichier runner.rb :
 

require 'sidekiq'require 'sidekiq-cron'  
require 'carioca'  
  
environment = ENV['RUBY_ENV'] ? ENV['RUBY_ENV'].to_sym : :development  
  
Carioca::Registry.configure do |spec|  
  spec.debug = true  
  spec.init_from_file = false  
  spec.log_file = '/tmp/tutoriel.log'  
  spec.config_file = './config/settings.yml'  
  spec.config_root = :runner  
  spec.environment = environment  
  spec.default_locale = :fr  
  spec.log_level = :debug  
  spec.locales_load_path << Dir["#{File.expand_path('./config/locales')}/*.yml"]  
  spec.debugger_tracer = :logger  
end  
  
class ApplicationController < Carioca::Container  
  inject service: :configuration  
end  
  
require_relative 'helpers/init'  
require_relative 'config/init'  
require_relative 'workers/init'  
  
Sidekiq::Cron::Job.destroy_all!  
  
Sidekiq.logger.info "Initialisation : #{get_config.application.name}"  
  
  
Sidekiq::Cron::Job.create(name: "Date",  
                          cron: '* * * * *', class: "Tutoriel::Workers::Date")  
  
Sidekiq.logger.info "Injection : job Date successfull"  
  
Sidekiq.logger.info 'Runner initialized'  

Ligne 1 à 3 : récupération des dépendances

    • ligne 5 : récupération de l'environnement
    • Ligne 7 à 18 : configuration de Carioca
    • Ligne 20 à 22 : Injection du service de configuration de Carioca
    • Ligne 24 à 26 : Import des fichiers
    • Ligne 28 : Suppression des jobs Sidekiq au lancement
    • Ligne 33 à 34 : Création du job Date avec un CRON de lancement toutes les minutes

Création du fichier de job, dans notre cas date.rb

 

module Tutoriel  module Workers  
    class Date  
      include Sidekiq::Worker  
      sidekiq_options retry: false  
  
      def perform  
          
      end  
    end  
  end  
end  

 

Vous pouvez désormais lancer Sidekiq avec la commande :

sidekiq -r ./runner.rb

Vous pouvez désormais lancer l'interface web de Sidekiq grâce à la commande :

rackup

Création du job de récupération de la date

  • Ajout d'une librairie Redis pour l'ajout de la date en base de données
    • Création d'un dossier lib
    • Ajout du fichier "lib/init.rb" 
Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each { |file| require file unless File.basename(file) == 'init.rb' }  
  • Ajout de l'url redis de la base de données générale de l'application
:runner:    
  :default:  
    :backend:  
      :redis:  
        :jobs:  
          :url: redis://localhost:6379/1  
        :tutoriel:  
          :url: redis://localhost:6379/2  
  
  :development:  
    :application:  
      :name: Tutoriel Sidekiq  
    • Ajout du fichier lib/redis.rb
require 'redis'  
module Backends  
  class RedisClient  
    include Singleton  
    attr_accessor :spool  
  
    def initialize  
      conf = { url: get_config.backend.redis.tutoriel.url }  
      @store = ::Redis.new conf  
    end  
  
    def list  
      @store.keys('*_*')  
    end  
  
    def get(entry:)  
      @store.get(entry)  
    end  
  
    def delete(entry:)  
      @store.del entry  
    end  
  
    def upsert(entry: , data:)  
      @store.set entry, data  
    end  
  
    alias update upsert  
    alias create upsert  
  
    def exist?(key:)  
      !@store.get(key).nil?  
    end  
  
    def flush  
      @store.flushdb  
    end  
  end  
end  
    • Ajout du helper "helpers/backend.rb"
module Tutoriel  module Helpers  
    module Backend  
      def get_redis  
        return Backends::RedisClient.instance  
      end  
    end  
  end  
end  

Définition du job à effectuer par le worker Date

require 'date'  
module Tutoriel  
  module Workers  
    class Date  
      include Sidekiq::Worker  
      include Tutoriel::Helpers::Backend  
      sidekiq_options retry: false  
  
      def perform  
        date = DateTime.now  
        get_redis.upsert(entry: 'date', data: date)  
      end  
    end  
  end  
end  
👍 Vous pouvez désormais lancer sidekiq et votre job va s’exécuter en fonction du CRON que vous avez défini.

Visualiser la base de données Redis dans VSCode pour voir si le changement est bien effectué

 

  • Allez sur l'onglet Extensions
  • Saisissez "database client" dans la barre de recherche
  • Sélectionnez le premier choix et installez l'extension
  • Redémarrez VSCode si nécessaire
  • Vous avez désormais deux nouveaux onglets sur votre barre latérale, allez sur l'onglet "NoSQL"
  • Cliquez sur la base Redis, puis sur l'onglet "2" en fonction de ce que vous avez choisi comme URL dans le fichier de configuration de l'application
  • vous visualisez le contenu de la base de données, vous avez une clé date définie, cliquez dessus pour obtenir sa valeur
  • Vous visualisez le contenu

Découverte de l'interface web Sidekiq

Rendez-vous sur localhost:9292 après avoir lancé votre interface web avec la commande "rackup".

Sur le dashboard vous pouvez visualiser toutes les queues ainsi que différentes informations à leur sujet.

Vous avez par exemple le nombre de jobs en échec, traités etc..

Vous pouvez également arrêter tous les processus ou uniquement certains.

Je vous invite à jouer avec l'exemple pour mieux découvrir la plateforme.

Mots clés

Romain GEORGES

Open Source evangelist & Ruby enthousiast