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

Reloading approach for rails runner #257

Closed
andyw8 opened this issue Feb 14, 2024 · 2 comments
Closed

Reloading approach for rails runner #257

andyw8 opened this issue Feb 14, 2024 · 2 comments

Comments

@andyw8
Copy link
Contributor

andyw8 commented Feb 14, 2024

We've now merged (but not yet released) #256 and it's working well.

We now need to consider how to deal with reloading, for example when running a migration which changes the schema.

Ideally we don't want to completely restart the runner, since that would be slow on large apps.

We're looking for a solution that could build upon the reloading mechanisms already present in Rails or Zeitwerk.

We could also make use of the LSP's ability to watch particular files for changes, which could trigger a notification to the runner process to reload particular files.

We'll need to do some research, but in the meantime @casperisfine we'd be interested to hear if you have any thoughts on this.

cc @vinistock

@casperisfine
Copy link

if you have any thoughts on this.

Right, so the classic autoloader used to try to be smart and remember the dependencies between files and only reload the ones that have changed or that depends on the ones that changed.

In theory with Zeitwerk you can still only unload the files you know have changed and it can reload them later on. The problem is that it open the doors to a lot of edge cases. e.g.

class Foo
  def some_method
    1
  end
end
class Bar
  FOO = Foo.new
end

If I edit foo.rb, you could only unload the Foo constant, but then Bar::FOO will continue to hold a reference to an instance of the old unloaded class. So you'd need to build a full dependency tree between the files or constant to try to optimize this without introducing weird edge cases.

I'd recommend first benchmarking unloading everything on changes on a reasonably sized application to see how well it would perform for the majority of users, and then start to optimize from there is really it doesn't seem viable.

For much larger applications like core, it may be acceptable to use heuristics that aren't always 100% correct.

Another thing to explore is whether everything need to be loaded upfront, maybe if you only load the constants you need you can get away with being totally lazy.

for example when running a migration which changes the schema.

So for migrations specifically, you don't need to reload the code, just call reset_column_information on models: https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-reset_column_information

@vinistock
Copy link
Member

This was completed in #282.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants