Fix variant price performance regressions #4639
Conversation
f556d91 to
772735d
Compare
d284db4 to
ed2e43b
Compare
Codecov Report
@@ Coverage Diff @@
## master #4639 +/- ##
==========================================
- Coverage 86.02% 86.01% -0.01%
==========================================
Files 571 571
Lines 14611 14605 -6
==========================================
- Hits 12569 12563 -6
Misses 2042 2042
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
|
Waiting on #4642 to fix the "coverage regression" :D |
tvdeyen
left a comment
There was a problem hiding this comment.
As someone having several hundreds prices per product in the database (welcome to Europe!) I like this very much.
For the "breaking" change: I cannot imagine a single scenario where I would want to keep prices for deleted variants anyway. And with just keeping them I am fine because as you said they will not appear anywhere anyway.
Thanks 👍🏻
|
@mamhoff, you can now rebase from master to fix the codecov issue 🙂 |
ed2e43b to
d42b0a0
Compare
|
Rebased! |
d42b0a0 to
996e312
Compare
jarednorman
left a comment
There was a problem hiding this comment.
I begrudgingly admit this is a good change, even if it's going to break one of my apps. 😅
Hey @jarednorman, in which way will your store be broken? |
|
We have custom pricing logic and have overridden the |
|
Maybe the whole thing belongs into the |
|
Yeah, there's still too many touch points for doing custom pricing right now. |
When we soft-delete a variant, we also soft-delete the variant's prices. In my opinion, this is not necessary, as the association between prices and variants includes discarded prices, and harmful, as it leads to price inconsistencies between a variant before discarding and after undiscarding (if the variant has a newer, but discarded, price, we have no way of knowing that that price should not be un-discarded along with the variant).
Using the `currently_valid` scope in this instance method leads to an "n+1" issue when getting prices for more than one variant. By sorting these in memory rather than in the database, we can save a lot of database round-trips.
This uses the redefined public method from the previous commit to detect the default price. Note that through using `reverse_each.detect` rather than `min` with a block we should be able to save some iterations.
|
I changed the label of this PR from Enhancement to Bug to reflect its content. @mamhoff going to merge, should we update the backport PRs as well? |
|
I can update them on Wednesday, if you want to Backport before that, go ahead! Thank you! |
|
Go ahead! |
💚 All backports created successfully
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
|
Done! Please, @mamhoff, please, take a look to be sure nothing is off. |
[v3.1] Merge pull request #4639 from mamhoff/do-not-discard-variant-prices-on-variant-discard
[v3.2] Merge pull request #4639 from mamhoff/do-not-discard-variant-prices-on-variant-discard
Until v3.2.3 duplicating a product duplicated the price. Since v3.2.4 the product duplication does not duplicate the price. Looks like it comes from the PR solidusio#4639 :/ To fix it we duplicate all of the master prices on the new_product.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Please, use Spree::Variant#default_price instead. Ref solidusio#4639.
Summary
This PR fixes a performance regression originating from #4076 and #4073. These two PRs fixed some inconsistencies by converting
variant.default_priceandvariant.currently_valid_pricesfrom associations to methods. Unfortunately, they also introduced n+1 queries by attaching scopes to thepricesassociation, essentially rendering any preloading of thepricesassociation futile.What this PR does is address both scope usages.
The first commit addresses the default price accessing
prices.with_discardedso that a discarded variant keeps its default price. We can get around this scope usage by simply not discarding prices when a variant is discarded. Because we only really load prices through variants and not the other way around, this should have no real-world impact (and will make the unlikely case of someone actually un-deleting a variant more predictable).The second commit addresses the
currently_valid_pricesmethod. It sorts thepricesassociation by priority in the database. By handling the sorting in ruby, we can get rid of the scope usage here.The third commit realizes that the
default_priceis the first price of thecurrently_valid_pricesthat fits thedefault_price_attributesand refactors some duplication out of theSpree::DefaultPriceconcern.Checklist
Check out our PR guidelines for more details.
The following are mandatory for all PRs:
The following are not always needed (
cross them outif they are not):I have attached screenshots to demo visual changes.I have opened a PR to update the guides.I have updated the readme to account for my changes.