Sidekiq échoue au démarrage après Zeitwerk sur docker dev

Nous avons récemment passé de la version 2.4.0.beta4 à la version 2.4.0.beta5, et Sidekiq ne parvient pas à démarrer avec la trace d’erreur suivante :

> $ bundle exec sidekiq -C config/sidekiq.yml
> constant SiteSetting::SiteSettingExtension non initialisé
> /discourse/app/models/site_setting.rb:5:in `<class:SiteSetting>'
> /discourse/app/models/site_setting.rb:3:in `<top (required)>'
> /discourse/vendor/bundle/ruby/2.5.0/gems/zeitwerk-2.1.10/lib/zeitwerk/kernel.rb:23:in `require'
> /discourse/vendor/bundle/ruby/2.5.0/gems/zeitwerk-2.1.10/lib/zeitwerk/kernel.rb:23:in `require'
> /discourse/vendor/bundle/ruby/2.5.0/gems/activesupport-6.0.0/lib/active_support/dependencies/interlock.rb:14:in `block in loading'
> /discourse/vendor/bundle/ruby/2.5.0/gems/activesupport-6.0.0/lib/active_support/concurrency/share_lock.rb:151:in `exclusive'
> /discourse/vendor/bundle/ruby/2.5.0/gems/activesupport-6.0.0/lib/active_support/dependencies/interlock.rb:13:in `loading'
> /discourse/config/initializers/004-message_bus.rb:120:in `<top (required)>'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/engine.rb:667:in `block in load_config_initializer'
> /discourse/vendor/bundle/ruby/2.5.0/gems/activesupport-6.0.0/lib/active_support/notifications.rb:182:in `instrument'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/engine.rb:666:in `load_config_initializer'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/engine.rb:624:in `block (2 levels) in <class:Engine>'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/engine.rb:623:in `each'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/engine.rb:623:in `block in <class:Engine>'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `instance_exec'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `run'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:61:in `block in run_initializers'
> /usr/local/lib/ruby/2.5.0/tsort.rb:228:in `block in tsort_each'
> /usr/local/lib/ruby/2.5.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
> /usr/local/lib/ruby/2.5.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
> /usr/local/lib/ruby/2.5.0/tsort.rb:431:in `each_strongly_connected_component_from'
> /usr/local/lib/ruby/2.5.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:50:in `each'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:50:in `tsort_each_child'
> /usr/local/lib/ruby/2.5.0/tsort.rb:415:in `call'
> /usr/local/lib/ruby/2.5.0/tsort.rb:415:in `each_strongly_connected_component_from'
> /usr/local/lib/ruby/2.5.0/tsort.rb:349:in `block in each_strongly_connected_component'
> /usr/local/lib/ruby/2.5.0/tsort.rb:347:in `each'
> /usr/local/lib/ruby/2.5.0/tsort.rb:347:in `call'
> /usr/local/lib/ruby/2.5.0/tsort.rb:347:in `each_strongly_connected_component'
> /usr/local/lib/ruby/2.5.0/tsort.rb:226:in `tsort_each'
> /usr/local/lib/ruby/2.5.0/tsort.rb:205:in `tsort_each'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/initializable.rb:60:in `run_initializers'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/application.rb:363:in `initialize!'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/railtie.rb:190:in `public_send'
> /discourse/vendor/bundle/ruby/2.5.0/gems/railties-6.0.0/lib/rails/railtie.rb:190:in `method_missing'
> /discourse/config/environment.rb:7:in `<top (required)>'
> /discourse/vendor/bundle/ruby/2.5.0/gems/sidekiq-5.2.7/lib/sidekiq/cli.rb:288:in `boot_system'
> /discourse/vendor/bundle/ruby/2.5.0/gems/sidekiq-5.2.7/lib/sidekiq/cli.rb:46:in `run'
> /discourse/vendor/bundle/ruby/2.5.0/gems/sidekiq-5.2.7/bin/sidekiq:12:in `<top (required)>'
> /discourse/vendor/bundle/ruby/2.5.0/bin/sidekiq:23:in `load'
> /discourse/vendor/bundle/ruby/2.5.0/bin/sidekiq:23:in `<top (required)>'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:74:in `load'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:74:in `kernel_load'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:28:in `run'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:463:in `exec'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:27:in `dispatch'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:18:in `start'
> /usr/local/bin/bundle:30:in `block in <main>'
> /usr/local/lib/ruby/site_ruby/2.5.0/bundler/friendly_errors.rb:124:in `with_friendly_errors'
> /usr/local/bin/bundle:22:in `<main>'

Avez-vous des pistes sur où chercher ensuite ? Merci !

Ceci n’est pas une installation suivant notre guide officiel, nous ne pouvons donc pas beaucoup vous aider.

Nous exécutons actuellement Discourse sur OpenShift, donc ce n’est certainement pas une installation standard. Je vais consulter le guide officiel pour vérifier si j’ai manqué quelque chose dans le déploiement actuel. Merci.

En fait, même la commande Docker suivante déclenche la même trace de pile dans ma machine Vagrant Discourse via VirtualBox :

vagrant ssh -c '(cd ~/discourse && sudo bin/docker/sidekiq)'

Tu es sûr de ça ? Le guide officiel ne mentionne rien concernant les démarrages manuels de Sidekiq, et il n’y a pas de dossier /home/discourse dedans.

Tu utilises une installation de développement en production :exploding_head: ??

J’utilise les commandes Docker pour tester et développer des plugins Discourse.

L’autre script que j’utilise actuellement est :

# Vider le cache temporaire de Discourse et lancer le serveur Rails de développement
vagrant ssh -c '(rm -rf ~/discourse/tmp/cache)'
vagrant ssh -c '(cd ~/discourse && sudo bin/docker/rails s)'

Bien sûr que non :smile:

@Falco, je pense que cela est lié à

Qu’en penses-tu ?

Ah, c’est possible. Le fait que vous n’ayez pas précisé qu’il s’agissait de votre environnement de développement et non d’un environnement de test n’a pas aidé.

Donc, vous affirmez que notre configuration Docker de développement est actuellement cassée ?

Oui, cela semble correct.

Le fait de revenir sur ce commit permet de faire fonctionner Sidekiq à nouveau.

On dirait que celle-ci est pour toi @kris.kotlarek

D’accord, je sais ce qui s’est passé ici, c’est de ma faute. J’ai supprimé beaucoup de require_dependency car ils ne sont plus nécessaires avec le chargeur automatique Zeitwerk.

Cependant, dans application.rb, nous avons ceci :

if !Sidekiq.server?
  config.autoload_paths += Dir["#{config.root}/lib"]
end

Cela signifie que Sidekiq ne recherche pas le répertoire lib pour trouver les dépendances et nous définissons explicitement ce qui est requis dans des fichiers spécifiques.

Je peux rétablir ce require_dependency pour les fichiers utilisés par Sidekiq ou supprimer cette garde dans application.rb.

Je pense que nous avons utilisé ce require explicite pour économiser de la mémoire pour les workers, donc nous devrons probablement suivre cette voie. Je vais rétablir require_dependency.

@sam, qu’en penses-tu ?

Nous devrions supprimer la protection. Je ne l’aime pas car on ne sait jamais si votre processus deviendra un Sidekiq ou non. Dans nos déploiements, nous avons : unicorn master → fork → sidekiq worker. Au moment du fork, application.rb avait déjà été analysé.

@kris.kotlarek Merci pour la correction. Sidekiq fonctionne désormais avec les plugins officiels de Discourse :+1:.

La plupart de mes plugins tiers avec des jobs ne fonctionnent plus :cry:. Cela est très probablement dû au commit suivant qui n’a pas été appliqué sur leurs classes Jobs::. :arrow_down:


Plugins tiers cassés

Vous avez raison, tous Jobs::Onceoff, Jobs::Base et Jobs::Scheduled nécessitent désormais ::

J’ai corrigé discourse-whos-online et créé des demandes de tirage pour d’autres plugins :

@kris.kotlarek Merci beaucoup :partying_face: :+1:. J’ai jeté un œil à votre publication concernant le chargeur automatique zeitwork. Existe-t-il un plan pour activer une fonctionnalité de rechargement automatique des plugins en développement afin d’accélérer le développement des plugins ?

Il reste encore des endroits contenant require ou require_dependency, mais beaucoup ont été supprimés.

Je pense que le code du plugin devrait maintenant être rechargé automatiquement sans problème. Nous devons faire quelques tests pour en être sûrs, mais j’ai un bon pressentiment :slight_smile:

Il semble que nous devions d’abord l’activer, comme l’indique sa documentation. Je l’ai testé en développement et aucune modification de plugin n’a été rechargée :cry:

Ce serait formidable. J’avais un peu d’espoir, mais vos paroles m’en donnent encore plus. Les développeurs de plugins vont adorer ça.