• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Architecture des applications web : quelles bonnes pratiques en 2020 ?
Architecture des applications web : quelles bonnes pratiques en 2020 ?
25 juin 2019
Quel hébergement pour vos applications web en 2020 ?
Quel hébergement pour vos applications web en 2020 ?
4 juillet 2019
Ressources > Articles techniques > Ruby, Sidekiq et Crystal

Ruby, Sidekiq et Crystal

Article écrit par Hugo Fabre

Dans le cadre d’une application web, il nous est tous déjà arrivés de devoir effectuer une tâche assez longue en asynchrone pour ne pas gêner le flux de notre application. En Ruby, la solution la plus populaire est d’utiliser l’outil Sidekiq.

Sidekiq est un outil développé en Ruby qui rend la création et l’utilisation de tâche asynchrone vraiment simple à intégrer dans une application existante. Pour fonctionner, Sidekiq gère une queue de tâches dans un Redis sous un format spécifique.

Une petite touche d’exotisme avec Crystal

Ce que nous savons moins, c’est que le développeur derrière Sidekiq, Mike Perham, a réimplémenté son outil en Crystal. Certes, il y a quelques fonctionnalités en moins, mais ce qui est intéressant, c’est que l’objectif a été de garder une compatibilité dans la manière de gérer la queue de tâches dans Redis. Par conséquent, il est en théorie très simple de rajouter à la file une demande d’exécution qui sera ensuite exécutée par un worker développé en Crystal.

Pour rappel, Crystal est un langage de programmation compilé dont la syntaxe est très inspirée de Ruby. Bien qu’il n’y ait pas de volonté de maintenir une compatibilité, en pratique sur du code simple, c’est souvent le cas.

L’idée de cet article est donc de présenter une preuve de concept d’une application Ruby qui ferait appel à un worker Crystal.

Pourquoi ?

Ici mon point de départ a été la découverte de la compatibilité entre Sidekiq Ruby et Sidekiq Crystal. Je me suis donc demandé dans quelle situation on pourrait en tirer avantage. La réponse est assez simple : nous avons besoin d’effectuer un traitement lourd en calcul dans une application Ruby sans rajouter une couche de complexité qui demanderait une grande adaptation aux développeurs (par exemple une extension native en C ou en Rust) et sans avoir un worker très long et gourmand en mémoire (typiquement pour de la génération de statistiques). Comme toute solution technique à un problème donné, il y a des avantages et des inconvénients.

Les points positifs

Ici, nous permettons à une application Ruby de tirer parti d’un langage performant et moins gourmand en mémoire. Sidekiq est un outil que tout le monde a l’habitude d’utiliser et le code du worker en Crystal sera facilement compréhensible pour un développeur Ruby. D’ailleurs, dans le cadre de cet article, le code du worker est totalement utilisable en Ruby comme en Crystal (bien sûr, c’est un exemple très simple).

Les points négatifs

Il ne sera pas forcément facile de faire revenir le résultat de notre worker dans notre application principale. Nous pouvons imaginer certaines solutions (WebSocket, requête HTTP ou même se connecter depuis le worker à la base de données de l’application, ou encore par e-mail si l’on n’a pas besoin d’un retour dans l’application) mais toutes ne sont pas adaptées à toutes les situations.

De plus Crystal n’ayant toujours pas de version stable, nous pouvons ne pas souhaiter l’intégrer à une application qui tourne en production.

En bref

Pour moi, il s’agit clairement d’une solution à garder sous le coude car elle peut présenter de gros avantages, mais uniquement dans certaines situations pour le moment.

L’implémentation

Eh bien en fait, même si le processus n’est pas documenté, l’implémentation reste finalement très simple. Avant toute chose, il y a quelques outils à installer à l’avance. Nous aurons besoin de Redis, Crystal et Ruby.

Ensuite il nous faudra un Gemfile pour l’application Ruby, celui-ci sera très simple :

# Gemfile  source 'https://rubygems.org'  gem 'sidekiq' 

Et un fichier shard.yml (plus ou moins l’équivalent du Gemfile pour une application Crystal) presque aussi simple :

# shard.yml  name: worker version: 0.1.0  authors:   - vous <vous@email.com>  targets:   crystal:     main: worker.cr  dependencies:   sidekiq:     github: mperham/sidekiq.cr     branch: master  crystal: 0.27.2  license: MIT 

On peut ensuite installer toutes nos dépendances :


gt; bundle install 

gt; shards install 

Et enfin le code. Le calcul que nous allons réaliser et un simple calcul de factoriel tout droit sortie de Rosetta Code.

Le worker :

# worker.cr  require "sidekiq" require "sidekiq/cli"  class FactorialWorker   include Sidekiq::Worker    def perform(n : Int32)     (2...n).each { |i| n *= i }     n.zero? ? 1 : n   end end   # See https://github.com/mperham/sidekiq.cr/wiki/Configuration ENV["LOCAL_REDIS"] = "redis://localhost:6379/8" ENV["REDIS_PROVIDER"] = "LOCAL_REDIS"  cli = Sidekiq::CLI.new server = cli.configure do |config|   # middleware would be added here end  cli.run(server) 

L’application Ruby :

# app.rb  require 'sidekiq'  redis_config = { url: 'redis://localhost:6379/8' }  Sidekiq.configure_client do |config|   config.redis = redis_config end  Sidekiq::Client.push('class' => 'FactorialWorker', 'args' =>[100_000]) 

On compile ensuite notre worker :


gt; crystal build --release worker.cr 

Sous MacOS j’ai rencontré une erreur du linker lors de la compilation qui ne trouvait pas OpenSSL via pkg-config :

ld: library not found for -lssl (this usually means you need to install the development package for libssl) clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Comme j’avais déjà installé OpenSSL via Homebrew j’ai simplement utilisé brew info openssl qui m’a indiqué la variable d’environnement à exporter. Dans mon cas j’ai utilisé :


gt; export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" 

On lance Redis, puis notre worker, et enfin notre application :


gt; redis-server 

gt; ./worker 

gt; bundle exec ruby app.rb 

Et on observe le résultat :

8728 TID-20vrgqo  JID=ef3eda4298c177869ea0dde7 INFO: Start 8728 TID-20vrgqo  JID=ef3eda4298c177869ea0dde7 INFO: Done: 0.000108 sec 

Plutôt simple non ?

Comme tout développeur digne de ce nom, nous ne pouvons pas résister à faire un petit benchmark ~qui n’a pas de sens~, je vous propose donc un worker ruby pour comparer :

# worker.rb  require "sidekiq"  class FactorialWorker   include Sidekiq::Worker    def perform(n)     (2...n).each { |i| n *= i }     n.zero? ? 1 : n   end end  Sidekiq.configure_server do |config|   config.redis = { url: 'redis://localhost:6379/8' } end 

On note que même si l’api de Sidekiq est différente le code métier est exactement le même. Ensuite on lance notre worker Ruby (sans oublier de couper celui en Crystal avant) et on relance notre application :


gt; bundle exec sidekiq -r ./worker.rb 

gt; bundle exec ruby app.rb 

Et voilà le résultat sur ma machine :

9384 TID-ouyqxa944 FactorialWorker JID-19031fc5db6010f45415f771 INFO: start 9384 TID-ouyqxa944 FactorialWorker JID-19031fc5db6010f45415f771 INFO: done: 6.656 sec 

Conclusion

Comme promis, l’implémentation est vraiment simple et le code de notre worker est facilement compréhensible et maintenable par un développeur Ruby sans besoin de monter en compétences sur un nouveau langage. Évidemment, pour respecter le contexte de preuve de concept, nous sommes restés sur une utilisation et une implémentation très simples. Je vous invite vivement à tester par vous-même et nous faire part de vos retours.

Nous nous quittons sur deux liens qui pourraient vous être utile pour vos recherches : le seul article que j’ai trouvé qui parle du sujet (en chinois mais heureusement le code est très compréhensible et il est toujours possible d’utiliser son outil de traduction préféré au besoin) de plus celui-ci propose une intégration dans une application Rails et enfin le readme de la version Crystal de Sidekiq qui liste les fonctionnalités manquantes par rapport à la version originale et explique les choix notamment sur les différences d’api entre les deux versions.

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter