Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #29991 - Enable Zeitwerk #10131

Open
wants to merge 22 commits into
base: develop
Choose a base branch
from

Conversation

ofedoren
Copy link
Member

@ofedoren ofedoren commented Apr 18, 2024

Based on #10076 (included). Added some more Puppetca -> PuppetCA renaming since we added a new acronym anyway.

Some require_dependency calls were removed, since with Zeitwerk there is no need in them (AFAIK they also don't work as with Rails' loader), some were changed to require (I think we can change them to require_relative).

I was able to load the application with Ansible, Bootdisk, Discovery, OpenSCAP, Puppet, REX, Tasks, Webhooks, Virt-who-config, Katello plugins (they do need some tweaks though and I'm planning to create a PR to each plugin I tested with) and successfully provision a host on libvirt with content management and SCAP scans.

There are still some issues like weird(?) require statements, non-conventional structure, etc, but we can deal with them later if we want to. It doesn't seem to be necessary anyway. What is necessary though is that we need to get rid of DEPRECATION WARNING: Initialization autoloaded the constants warning. It's huge, annoying and may become an error in the future. Not sure now how to do so, but can be done in a separate PR done here.

Comment on lines 13 to 16
require_dependency('proxy_status/version')
require_dependency('proxy_status/tftp')
require_dependency('proxy_status/puppet_ca')
require_dependency('proxy_status/logs')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you lazy load the application, are they properly registered? I think that's one worry I had, which mostly affects development environments.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have eager loading in dev mode, but yeah, worth checking anyway...

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#single-table-inheritance it says you should turn on eager_load, which we mostly do:

$ rg eager_load config
config/application.rb
152:    config.eager_load_paths += ["#{config.root}/lib"]
370:    # We use the routes_reloader before the to_prepare and eager_load callbacks
404:      dynflow.eager_load_actions!

config/environments/test.rb
16:  config.eager_load = false

config/environments/production.rb
7:  config.eager_load = true

config/environments/development.rb
10:  config.eager_load = true

Perhaps this explains why you saw it work in development, but not in tests?

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the logic we should keep? Nothing in lib and everything in app/lib?

lib/timed_cached_store.rb Outdated Show resolved Hide resolved
config/initializers/6_preload_stis.rb Outdated Show resolved Hide resolved
config/environments/test.rb Outdated Show resolved Hide resolved
@@ -1,6 +1,6 @@
require 'test_helper'

class HttpProxyTest < ActiveSupport::TestCase
class Foreman::HttpProxyTest < ActiveSupport::TestCase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be in the Foreman namespace? Because it's in the foreman directory in tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mocha/minitest (not sure) has its own logic for constant lookups and probably due eager loading it treats this class as if it was test/unit/http_proxy_test.rb. It finds the same constant HttpProxy, which mistreats the one with additional Foreman:: scope.

@@ -1,5 +1,5 @@
module Foreman
module HTTPProxy
module HttpProxy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps HTTP needs to be its own acronym as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you then update #10076? For some reason though, I didn't make this an acronym in my alternative. Maybe there are more pitfalls than it seems...

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going through open issues on https://projects.theforeman.org/issues/29991 and highlighted a few that are open and I think are related.

I'm not sure https://projects.theforeman.org/issues/33975 is still an issue.


Rails.application.config.before_initialize do
# load topbar
Menu::Loader.load
end

Foreman.settings.load_definitions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, it seems this gets executed as part of https://github.com/theforeman/foreman/blob/develop/config/initializers/foreman.rb#L37 anyway. It also contains Foreman.settings.load_values, which is called in after_initialize callback. I think that is redundant...

I mean, I'm not 100% sure why we have it as we do, but for me it seems that Foreman.settings.load in to_prepare is sufficient and does the same thing as combination of Foreman.settings.load_definitions here and Foreman.settings.load_values in after_initialize. For me it also seems like currently we try to load the definitions and values 2 times.

Should I change the commit message for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it for now here as is, 'cause I didn't yet tested these new changes with plugins (working on it though).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should, since it get's only loaded explicitly in https://github.com/theforeman/foreman/blob/develop/config/application.rb#L385.

Should I change the commit message?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please. And if it can be merged today without the whole Zeitwerk changes, then submitting it as its own PR will be great.

@ofedoren
Copy link
Member Author

Perhaps this explains why you saw it work in development, but not in tests?

Nope, that was a few different issues

@ofedoren
Copy link
Member Author

What's the logic we should keep? Nothing in lib and everything in app/lib?

Currently I'm trying to clean things up a bit. Per my thinking (and hopefully Rails') /lib should not contain any (auto|re)loadable, but rather code which should be required as with external libs. Since we have a lot of code which is needed during initialization times, I'd also say that that code should be in /lib unless it should be used in to_prepare, which can be autoloadable. (Rails note: You cannot autoload code in the autoload paths while the application boots. In particular, directly in config/initializers/*.rb. Please check [Autoloading when the application boots](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoloading-when-the-application-boots) down below for valid ways to do that.)

Such (auto|re)loadable code, which is not a concern/model/controller/etc I've moved into app/lib to eliminate some require calls. I guess it could go into app/services, which seems to be abused for similar purposes, but that directory is even less "conventional"...

Although, I still think that we far away from proper (auto|re)loading for dev purposes. As of now I'm more in scope of making Zeitwerk work, maybe someone in the future will have time to refactor a bit, so we can maybe disable eager loading and use reloading in other places than concerns and models (those I think still work as expected).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
2 participants