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

Move InternalMetadata to an independent object #45982

Merged
merged 1 commit into from
Sep 12, 2022

Conversation

eileencodes
Copy link
Member

@eileencodes eileencodes commented Sep 9, 2022

Followup to #45908 to match the same behavior as SchemaMigration

Previously, InternalMetadata inherited from ActiveRecord::Base. This is problematic for multiple databases and resulted in building the code in AbstractAdapter that was previously there. Rather than hacking around the fact that InternalMetadata inherits from Base, this PR makes InternalMetadata an independent object. Then each connection can get it's own InternalMetadata object. This change required defining the methods that InternalMetadata was depending on ActiveRecord::Base for (ex create!). I reimplemented only the methods called by the framework as this class is no-doc's so it doesn't need to implement anything beyond that. Now each connection gets it's own InternalMetadata object which stores the connection.

This change also required adding a NullInternalMetadata class for cases when we don't have a connection yet but still need to copy migrations from the MigrationContext. Ultimately I think this is a little weird - we need to do so much work to pick up a set of files? Maybe something to explore in the future.

Aside from removing the hack we added back in #36439 this change will enable my work to stop clobbering and depending directly on Base.connection in the rake tasks. While working on this I discovered that we always have a ActiveRecord::InternalMetadata because the connection is always on Base in the rake tasks. This will free us up to do less hacky stuff in the migrations and tasks.

Both schema migration and internal metadata are blockers to removing Base.connection and Base.establish_connection from rake tasks, work that is required to drop the reliance on Base.connection which will enable more robust (and correct) sharding behavior in Rails..

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
  • There are no typos in commit messages and comments.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Feature branch is up-to-date with main (if not - rebase it).
  • Pull request only contains one commit for bug fixes and small features. If it's a larger feature, multiple commits are permitted but must be descriptive.
  • Tests are added if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.
  • PR is not in a draft state.
  • CI is passing.

@eileencodes eileencodes force-pushed the redo-internal-metadata branch 3 times, most recently from 50e2b6d to 9f0b18f Compare September 9, 2022 17:32
@rails-bot rails-bot bot added the railties label Sep 9, 2022
@eileencodes eileencodes force-pushed the redo-internal-metadata branch 2 times, most recently from 11f64b7 to 8824422 Compare September 9, 2022 18:57
Followup to rails#45908 to match the same behavior as SchemaMigration

Previously, InternalMetadata inherited from ActiveRecord::Base. This is
problematic for multiple databases and resulted in building the code in
AbstractAdapter that was previously there. Rather than hacking around
the fact that InternalMetadata inherits from Base, this PR makes
InternalMetadata an independent object. Then each connection can get it's
own InternalMetadata object. This change required defining the methods
that InternalMetadata was depending on ActiveRecord::Base for (ex
create!). I reimplemented only the methods called by the framework as
this class is no-doc's so it doesn't need to implement anything beyond
that. Now each connection gets it's own InternalMetadata object which
stores the connection.

This change also required adding a NullInternalMetadata class for cases
when we don't have a connection yet but still need to copy migrations
from the MigrationContext. Ultimately I think this is a little weird -
we need to do so much work to pick up a set of files? Maybe something to
explore in the future.

Aside from removing the hack we added back in rails#36439 this change will
enable my work to stop clobbering and depending directly on
Base.connection in the rake tasks. While working on this I discovered
that we always have a ActiveRecord::InternalMetadata because the
connection is always on Base in the rake tasks. This will free us up
to do less hacky stuff in the migrations and tasks.

Both schema migration and internal metadata are blockers to removing
`Base.connection` and `Base.establish_connection` from rake tasks, work
that is required to drop the reliance on `Base.connection` which will
enable more robust (and correct) sharding behavior in Rails..
@eileencodes eileencodes merged commit 53992c1 into rails:main Sep 12, 2022
@eileencodes eileencodes deleted the redo-internal-metadata branch September 12, 2022 14:05
eileencodes added a commit to eileencodes/rails that referenced this pull request Sep 12, 2022
Since changing internal metadata to no longer inherit from Base
in rails#45982 I accidentally changed the behavior when a key's value is the
same. Prior to this change the record would not be updated if the
environment key was found an the value had not changed. So instead of
just checking whether we have an entry here we also need to check if the
value should actually be updated, otherwise we should return the entry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants