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

Fix variant price performance regressions #4639

Conversation

mamhoff
Copy link
Contributor

@mamhoff mamhoff commented Sep 23, 2022

Summary

This PR fixes a performance regression originating from #4076 and #4073. These two PRs fixed some inconsistencies by converting variant.default_price and variant.currently_valid_prices from associations to methods. Unfortunately, they also introduced n+1 queries by attaching scopes to the prices association, essentially rendering any preloading of the prices association futile.

What this PR does is address both scope usages.

The first commit addresses the default price accessing prices.with_discarded so 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_prices method. It sorts the prices association 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_price is the first price of the currently_valid_prices that fits the default_price_attributes and refactors some duplication out of the Spree::DefaultPrice concern.

Checklist

Check out our PR guidelines for more details.

The following are mandatory for all PRs:

  • I have written a thorough PR description.
  • I have kept my commits small and atomic.
  • I have used clear, explanatory commit messages.

The following are not always needed (cross them out if they are not):

  • I have added automated tests to cover my changes.
  • 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.

@github-actions github-actions bot added the changelog:solidus_core Changes to the solidus_core gem label Sep 23, 2022
@mamhoff mamhoff marked this pull request as draft September 23, 2022 16:25
@mamhoff mamhoff force-pushed the do-not-discard-variant-prices-on-variant-discard branch 2 times, most recently from f556d91 to 772735d Compare September 23, 2022 17:13
@github-actions github-actions bot added the changelog:solidus_backend Changes to the solidus_backend gem label Sep 24, 2022
@mamhoff mamhoff force-pushed the do-not-discard-variant-prices-on-variant-discard branch from d284db4 to ed2e43b Compare September 24, 2022 09:24
@codecov
Copy link

codecov bot commented Sep 24, 2022

Codecov Report

Merging #4639 (3f4578a) into master (20a47c8) will decrease coverage by 0.00%.
The diff coverage is 100.00%.

@@            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              
Impacted Files Coverage Δ
core/app/models/concerns/spree/default_price.rb 100.00% <100.00%> (ø)
core/app/models/spree/variant.rb 100.00% <100.00%> (ø)
core/app/models/spree/variant/price_selector.rb 100.00% <100.00%> (ø)

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@mamhoff
Copy link
Contributor Author

mamhoff commented Sep 26, 2022

Waiting on #4642 to fix the "coverage regression" :D

@mamhoff mamhoff marked this pull request as ready for review September 26, 2022 08:21
Copy link
Member

@tvdeyen tvdeyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 👍🏻

@tvdeyen tvdeyen requested a review from a team September 26, 2022 14:14
@waiting-for-dev
Copy link
Contributor

@mamhoff, you can now rebase from master to fix the codecov issue 🙂

@waiting-for-dev waiting-for-dev added the type:enhancement Proposed or newly added feature label Sep 27, 2022
@mamhoff mamhoff force-pushed the do-not-discard-variant-prices-on-variant-discard branch from ed2e43b to d42b0a0 Compare September 28, 2022 07:26
@mamhoff
Copy link
Contributor Author

mamhoff commented Sep 28, 2022

Rebased!

@mamhoff mamhoff force-pushed the do-not-discard-variant-prices-on-variant-discard branch from d42b0a0 to 996e312 Compare September 28, 2022 09:24
Copy link
Contributor

@waiting-for-dev waiting-for-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!!

Copy link
Member

@jarednorman jarednorman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I begrudgingly admit this is a good change, even if it's going to break one of my apps. 😅

@waiting-for-dev
Copy link
Contributor

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?

@jarednorman
Copy link
Member

We have custom pricing logic and have overridden the currently_valid scope on prices, but this changes the currently_valid_prices method to no longer delegate to currently_valid.

@mamhoff
Copy link
Contributor Author

mamhoff commented Sep 29, 2022

Maybe the whole thing belongs into the variant_price_selector_class.

@jarednorman
Copy link
Member

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.
@kennyadsl kennyadsl added type:bug Error, flaw or fault and removed type:enhancement Proposed or newly added feature labels Oct 17, 2022
@kennyadsl
Copy link
Member

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?

@kennyadsl kennyadsl merged commit 425c82f into solidusio:master Oct 17, 2022
@mamhoff
Copy link
Contributor Author

mamhoff commented Oct 17, 2022

I can update them on Wednesday, if you want to Backport before that, go ahead! Thank you!

@kennyadsl
Copy link
Member

@mamhoff we could try using #4678 for this. What do you think?

@mamhoff
Copy link
Contributor Author

mamhoff commented Oct 24, 2022

Go ahead!

@github-actions
Copy link

💚 All backports created successfully

Status Branch Result
v3.2
v3.1

Questions ?

Please refer to the Backport tool documentation and see the Github Action logs for details

@waiting-for-dev
Copy link
Contributor

waiting-for-dev commented Oct 24, 2022

Done! Please, @mamhoff, please, take a look to be sure nothing is off.

waiting-for-dev added a commit that referenced this pull request Nov 8, 2022
[v3.1] Merge pull request #4639 from mamhoff/do-not-discard-variant-prices-on-variant-discard
waiting-for-dev added a commit that referenced this pull request Nov 8, 2022
[v3.2] Merge pull request #4639 from mamhoff/do-not-discard-variant-prices-on-variant-discard
Roddoric added a commit to Roddoric/solidus that referenced this pull request Mar 9, 2023
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.
github-actions bot pushed a commit that referenced this pull request Mar 10, 2023
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 #4639 :/

To fix it we duplicate all of the master prices on the new_product.

(cherry picked from commit 00cac06)
github-actions bot pushed a commit that referenced this pull request Mar 10, 2023
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 #4639 :/

To fix it we duplicate all of the master prices on the new_product.

(cherry picked from commit 00cac06)
github-actions bot pushed a commit that referenced this pull request Mar 10, 2023
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 #4639 :/

To fix it we duplicate all of the master prices on the new_product.

(cherry picked from commit 00cac06)
kennyadsl added a commit to nebulab/solidus that referenced this pull request Mar 17, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Mar 17, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Mar 21, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Apr 12, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Apr 14, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Apr 18, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
kennyadsl added a commit to nebulab/solidus that referenced this pull request Apr 24, 2023
Please, use Spree::Variant#default_price instead.

Ref solidusio#4639.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog:solidus_backend Changes to the solidus_backend gem changelog:solidus_core Changes to the solidus_core gem type:bug Error, flaw or fault
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants