Do not reload rake tasks when under add-on environment #2061
+5
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
This PR fixes at least one of the reasons for the memory bloat in the LSP add-on. To check for pending migrations, we were repeatedly loading rake tasks. That will invoke the blocks used to define rake tasks multiple times and continue to put more and more stuff into the global namespace, which makes memory grow.
We analyzed some heap dumps with Peter and after this change the number of strings,
DATA
objects and even regexes stops growing after multiple invocations.Implementation
When the add-on is running, Tapioca is already inside a Rails application context, where rake tasks have been loaded.
We do not need to continuously load the tasks over and over again.
Important note
While this PR fixes a significant part of the memory bloat, it doesn't address one important usability aspect.We cannot invokeRake::Task["db:abort_if_pending_migrations"].invoke
when running from inside the add-on because that rake tasks aborts the current process, which means it would cause the Rails runner server to exit prematurely and crash.We will need to re-think how we do this because there are a few constraints that we need to account for. For example, applications can enhance or redefine thedb:abort_if_pending_migrations
task, so we cannot reach into Rails internals to check if there are any pending migrations.At the same time, we can't not check if there are migrations pending because then we would generate incorrect DSLs.One possibility of what we can do, which isn't ideal but I can't think of anything else, is to fork the current process and run the task inside a fork. Then we check if the exit status was successful and decide what to do from there, which allows us to show a nice message to the user. But forking every single time to check this might be expensive.We may need a more sophisticated approach, like checking for pending migrations only once during boot and then watching the files created under thedb
directory, so that we can avoid the forks and still have some sense of new migrations.EDIT: I changed this PR to never check if there are pending migrations on add-on mode. I'm working on making the Rails add-on check and offer running migrations to the user automatically.