Sidekiq no inicia después de Zeitwerk en docker dev

Recientemente actualizamos de la versión 2.4.0.beta4 a la 2.4.0.beta5 y Sidekiq falla al iniciarse con el siguiente rastreo de errores:

> $ bundle exec sidekiq -C config/sidekiq.yml
> uninitialized constant SiteSetting::SiteSettingExtension
> /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>'

¿Alguna orientación sobre dónde buscar a continuación? ¡Gracias!

Esta no es una instalación que siga nuestra guía oficial, por lo que no podemos ayudarte mucho.

Actualmente estamos ejecutando Discourse en OpenShift, así que seguro que no es una instalación estándar. Revisaré la guía oficial para ver si me perdí algo en la implementación actual. Gracias.

De hecho, incluso el siguiente comando de Docker desencadena la misma traza de pila en mi máquina Vagrant de Discourse sobre VirtualBox:

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

¿Estás seguro de eso? La guía oficial no menciona nada sobre inicios manuales de Sidekiq y tampoco hay una carpeta /home/discourse en ella.

¿Estás ejecutando una instalación de desarrollo en producción :exploding_head:??

Estoy usando los comandos de Docker para probar y desarrollar complementos de Discourse.

El otro script que estoy usando actualmente es:

# Limpiar la caché temporal de Discourse e iniciar Rails en modo desarrollo
vagrant ssh -c '(rm -rf ~/discourse/tmp/cache)'
vagrant ssh -c '(cd ~/discourse && sudo bin/docker/rails s)'

Por supuesto que no :smile:

@Falco Creo que está relacionado con

¿Qué opinas?

Puede que sí lo sea. El hecho de que no hayas aclarado que se trata de tu configuración de desarrollo y no de un entorno de desarrollo no ayudó.

¿Estás diciendo que nuestra configuración de desarrollo con Docker está actualmente rota?

Sí, parece que sí.

Revertir ese commit hace que sidekiq funcione de nuevo.

Parece que este es uno para ti @kris.kotlarek

Ok, sé lo que ocurrió aquí, es mi culpa. Eliminé muchos require_dependency ya que ya no son necesarios al usar el autocargador Zeitwerk.

Sin embargo, en application.rb tenemos esto:

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

Esto significa que Sidekiq no busca en el directorio lib para encontrar dependencias y definimos explícitamente lo que se requiere en archivos específicos.

Puedo volver a incluir ese require_dependency para los archivos que utiliza Sidekiq o eliminar esa condición en application.rb.

Supongo que usamos ese require explícito para ahorrar algo de memoria en los workers, así que probablemente deberíamos seguir ese camino. Volveré a agregar require_dependency.

@sam, ¿cuál es tu opinión?

Deberíamos eliminar la protección; no me gusta porque no tienes forma de saber si tu proceso se convertirá en Sidekiq o no. En nuestras implementaciones tenemos: unicorn master → fork → sidekiq worker. En el momento del fork, application.rb ya había sido analizado.

@kris.kotlarek Gracias por la corrección. Sidekiq ahora funciona junto con los plugins oficiales de Discourse :+1:.

La mayoría de mis plugins de terceros con trabajos no funcionan ahora :cry:. Lo más probable es que esto se deba a que el siguiente commit no se aplicó en sus clases Jobs::. :arrow_down:


Plugins de terceros rotos

Tienes razón, ahora todos Jobs::Onceoff, Jobs::Base y Jobs::Scheduled requieren ::

Arreglé discourse-whos-online y creé solicitudes de extracción para otros plugins:

@kris.kotlarek ¡Muchas gracias! :partying_face: :+1:. He echado un vistazo a tu publicación sobre el cargador automático de zeitwerk. ¿Existe algún plan para habilitar una función de recarga automática de plugins en modo desarrollo para agilizar el desarrollo de plugins?

Aún hay lugares que contienen require o require_dependency, pero muchos han sido eliminados.

Creo que ahora el código del plugin debería recargarse automáticamente sin problemas. Necesitamos probar un poco para asegurarnos, pero tengo un buen presentimiento :slight_smile:

Parece que primero necesitamos habilitarlo según su documentación. Lo probé en desarrollo y no se recargaron cambios en los plugins :cry:

Esto sería genial. Tenía algo de esperanza, pero tus palabras me dan más esperanza. A los desarrolladores de complementos les encantará esto.