Code-reloading issues in stale classes
We have stale classes in memory when code-reloading is enabled because we reference these classes in non-autoloaded classes.
A prime example of this is middleware (Rack / Sidekiq) because these are held in memory. And then, when any code is changed and all autoloaded classes are unloaded, these would be stale.
Normally, these would work fine and these references would just not pick up any changes made to the classes. But there is a problem when this stale class tries to autoload another class.
You will get an error like:
ArgumentError:
A copy of Gitlab::SidekiqMiddleware::AdminMode::Client has been removed from the module tree but is still active!
# ./lib/gitlab/sidekiq_middleware/admin_mode/client.rb:11:in `call'
# ./lib/gitlab/sidekiq_status/client_middleware.rb:10:in `call'
In this specific case, this class is trying to autoload Feature
and Gitlab::SidekiqMiddleware::AdminMode::Client.const_missing
is triggered which then raises this exception because the current module is stale.
A workaround is to use a fully qualified class name ::Feature
so that Object.const_missing
will be triggered.
https://stackoverflow.com/a/29710188 has more details
When we switched to Zeitwerk we also saw a similar problem although the exception is different. Even though Zeitwerk doesn't use const_missing
, there seems to be a similar problem with autoloading in these stale classes.
An example report is described below:
Zeitwerk seems to have some quirks on how it handles name lookups in ruby. We had to revert Zeitwerk support !27539 (merged) because, after a code-reload is triggered, we were having the following error preventing the execution flow to continue:
Unexpected error while processing request: uninitialized constant Gitlab::Metrics::RequestsRackMiddleware::RequestsRackMiddleware
the problem is that zeitwerk is duplicating the name of the class: RequestsRackMiddleware
when we try to call it to reach the a class method in:
http://gitlab.com/gitlab-org/gitlab/blob/70e9450ecaf97c0b6a934f71ef6d90511966377e/lib/gitlab/metrics/requests_rack_middleware.rb#L47-57
A way to fix this and other related issues is to use self.class
instead of naming the class. Another alternative is to use the full namespace prefix with ::
:
::Gitlab::Metrics::RequestsRackMiddleware