这是Rails v5.2.3。我有一个特殊的Sidekiq作业,其中作业的许多示例似乎挂起了20多分钟。在队列所在的同一台机器上,当发生这种情况时,我可以在Rails控制台中运行相同的代码,它在5秒内完成。
我从Sidekiq屏幕上确定了有问题的PID,然后运行:kill -TTIN <pid>
下面的行在文件中出现了两次,我猜这意味着来自同一进程的两个线程试图加载同一个文件:
Oct 13 17:04:08 myapp-production sidekiq[1217886]: /myapp/shared/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/core_ext/module/introspection.rb:35:in `parent'
Oct 13 17:04:08 myapp-production sidekiq[1217886]: /myapp/shared/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:516:in `load_missing_constant'
Oct 13 17:04:08 myapp-production sidekiq[1217886]: /myapp/shared/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:195:in `const_missing'
Oct 13 17:04:08 myapp-production sidekiq[1217886]: /myapp/releases/20221013144458/lib/mixins/query_builder.rb:294:in `generate_sql'
我确实在代码中的不同地方有一些require
,我刚刚确定这显然是不好的。但是,我不会使用上面列出的文件:lib/mixins/query_builder.rb
。它是从lib/classes
中的几个不同类中extend
艾德的模块。
在我的config/application.rb
文件中,我有:
config.enable_dependency_loading = true
config.eager_load_paths += %W[
#{config.root}/app/actions
#{config.root}/app/organizers
#{config.root}/lib/my_stuff
#{config.root}/lib/mixins
#{config.root}/lib/classes
]
config.autoload_paths += %W[
#{config.root}/app/actions
#{config.root}/app/organizers
#{config.root}/lib
#{config.root}/lib/my_stuff
#{config.root}/lib/mixins
#{config.root}/lib/classes
#{config.root}/lib/*
我承认这很混乱,我不知道这里发生了什么,我确实在生产中将config.eager_load
设置为true,在开发中设置为false。
那么,如果lib/mixins
同时存在于eager_load_paths
和autoload_paths
中,为什么会触发ActiveSupport的const_missing
?我应该如何解决这种情况?
另外,将QueryBuilder
作为一个对象,使我可以创建一个示例,以避免两个线程使用同一个程序,这是否会更好?换句话说,将QueryBuilder
中的特性借给多个类,extend
是不是一种错误的方法?
作为第二个请求,如果有人能给我指出正确的方向,正确的方式来配置我的eager_load_paths
和autoload_paths
,这将有助于大量之前升级这个应用程序。
事先非常感谢您的帮助。
1条答案
按热度按时间nfeuvbwi1#
这是“为什么我看到自动加载”的答案。
在紧急加载期间,仍可能发生自动加载。
让我们想象一下
如果Rails急于加载
Foo
,而此时lib/mixins/query_builder.rb
还没有被访问,那么仅仅对foo.rb
的求值就会触发第2行中QueryBuilder
的自动加载。那个配置有点乱(就像你说的)。我们可以努力简化它,你喜欢的。
为什么在控制台中的作业需要+20分钟和5分钟?不知道是否与此有关。当Sidekiq启动时,应用程序已经启动,文件已经加载完毕。