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

Remove memoization for limited_count #43816

Merged
merged 1 commit into from Dec 10, 2021

Conversation

jpawlyn
Copy link
Contributor

@jpawlyn jpawlyn commented Dec 9, 2021

Summary

If a relation's records are not loaded and @limited_count gets set, when some of the records are subsequently deleted then the memoized value for @limited_count is inconsistent with the value returned by a call to size. In such a case calls to one? and many? can be incorrect. This is a fix for #43801.

Other Information

since if a relation's records are not loaded and @limited_count gets set, when some of the records are subsequently deleted then the memoized value for @limited_count is inconsistent with the value returned by a call to size. In such a case calls to one? and many? can be incorrect.
@rafaelfranca rafaelfranca merged commit 9ae41cb into rails:main Dec 10, 2021
rafaelfranca added a commit that referenced this pull request Dec 10, 2021
@jonathanhefner
Copy link
Member

The build failures here are related. I believe this effectively reverts #42143, so perhaps it should be entirely reverted?

@rafaelfranca
Copy link
Member

Good find. I think we can keep both if we invalidate the cache of @limited_count when mutating the relation. @jpawlyn can you take a look?

@rafaelfranca
Copy link
Member

I'm going to revert this PR in the mean time.

rafaelfranca added a commit that referenced this pull request Dec 10, 2021
rafaelfranca added a commit that referenced this pull request Dec 10, 2021
…lation"

This reverts commit 9ae41cb, reversing
changes made to e454705.

CI is broken.
@jpawlyn
Copy link
Contributor Author

jpawlyn commented Dec 12, 2021

Good find. I think we can keep both if we invalidate the cache of @limited_count when mutating the relation. @jpawlyn can you take a look?

Sure. In the test:

posts.where.not(id: Post.first).destroy_all

the call to where looks to be spawning a new relation so not sure how to invalidate the cache of the original relation for this scenario. Any pointers appreciated.

If there's no obvious way to do the cache invalidation, should we keep with the memoization removal, retain the limited_count method for performance and remove the 2 failing memoization tests?

@matthewd
Copy link
Member

Hmm, yeah, I think that test is unrepresentative of expected behaviour (even if it was the historical observable behaviour).

Relations are expected to memoize information about what's in the database after they query it, and will not notice if the database is manipulated afterwards [except very directly through that relation itself]. If you posts.each { .. } (or simply posts.load), then do that destroy_all, then loop through posts afterwards, you'll see posts that have since been destroyed. Given we make no attempt to prevent that in the general case (i.e., if you make DB changes after a relation is loaded, you need to reload it to ensure you're seeing current truth), I don't think we need to give extra consideration to one? here. (The "two methods called at different times can disagree" issue is also visible if you call size early, then later to_a after the destroy: you'll get fewer records than size predicts.)

@jpawlyn
Copy link
Contributor Author

jpawlyn commented Dec 13, 2021

(The "two methods called at different times can disagree" issue is also visible if you call size early, then later to_a after the destroy: you'll get fewer records than size predicts.)

I guess the strange behaviour here though is that the calls to size and one? are made at the same time, with size returning 1 and one? returning false. I just wonder if this is an unnecessary inconsistency?

@matthewd
Copy link
Member

matthewd commented Dec 14, 2021

Call size, perform destroy, then: relation.size == relation.to_a.size # => false

Sorry, I made the same mistake I did in #42143 -- my brain remains entirely (and falsely) convinced that size memoizes.

rafaelfranca added a commit that referenced this pull request Dec 15, 2021
…ny-on-relation""

This reverts commit 1410c3f.

Fixes #43801.

Since we can't memoize the result of the count query, we can't make sure
subsequent calls will only execute one query.
rafaelfranca added a commit that referenced this pull request Dec 15, 2021
…ny-on-relation""

This reverts commit 1410c3f.

Fixes #43801.

Since we can't memoize the result of the count query, we can't make sure
subsequent calls will only execute one query.
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

4 participants