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

feat(medusa): Cart and totals improvements #2475

Merged
merged 31 commits into from
Nov 14, 2022
Merged

Conversation

adrien2p
Copy link
Member

@adrien2p adrien2p commented Oct 20, 2022

Metric: cart completion with 4/5 items took 11 seconds when it takes less than 2 seconds now, it can vary depending on the machines. As part of those 2 sec there is 1 sec for stripe (called 3 times) and few hundreds milliseconds for external tax api call

Cart/Order performance improvement, more specifically during cart completion

The purpose of that Pr is to drastically reduce the response time of the cart completion strategy.
The improvements made here have also some side effects which improve the performances of other part of the code but
it was not the main goal of it.

All improvements will be applicable in later PR's to also improve everything related to cart and order end point
and totals calculations.

Totals calculation

Some improvements have been made to the totals service, in order to not break the existing API right away, it has been
decided by myself (but can evolve) to create a new service TotalsNewService where all new methods are implemented and consumed from.

Generally speaking there is no mention of any specific entities such as the Cart or Order entity as the different methods
explicitly describe the expected arguments which makes it flexible and do not enforce to pass a specific entity
but only an object that contains the expected properties. The overall idea is to have a totals service
less coupled to specific entities but just do its job which is to compute some calculations based on the
expected arguments.

The overall changes are the following:

  • getLineItemsTotals

This method accept a collection of items as well as some options

  • includeTax which only enforce the tax_lines to exist either provided by the item itself or the ones that will be queried internally through the tax provider service if useExistingTaxLines is not set to true
  • calculationContext which is the usual calculation context
  • taxRate which is only there to support backward compatibility. I choose to keep it but the methods have been separated
  • useExistingTaxLines which enforce the usage of the tax lines from the items. Can be useful in cases where
    the tax_lines already exists or have been already fetched and assigned by the consumer in order to not re fetch them if
    it is not necessary

This method is of a higher rank as it will only take care of using the right tax lines and call another method
to compute the totals of each item.

To compute the totals of each item there is now two methods which are described bellow

  • getLineItemTotalsLegacy

As the name describe, this method calcul the totals for the legacy backward compatibility cases where the taxRate is
explicitly provided to be used. It is normally in the case of the order.

  • getLineItemTotals

Which is used to calculate the totals with the new approach using the tax lines.
In that method the options includeTax as been kept only to throw if no tax lines are provided by any of the
possible way, either from the item or explicitly provided


  • getLineItemRefund

This method take a partial item composed of the necessary properties needed to calculate the refund amount.
It is also possible to provide an optional taxRate to calculate it the legacy way where the method will call
the getLineItemRefundLegacy method for that.

  • getLineItemRefundLegacy

Now let's look at the gift card part of the totals below

  • getGiftCardTotals

This method take now a maximun amount that can be gifted, it is possible to pass either the giftCards or the giftCardTransactions
as part of the options. If the giftCardTransactions are provided then a separate method will be called getGiftCardTransactionsTotals
in order to provided the right calculation for that collection otherwise the giftCards will be used
to calculate the amount.

  • getGiftCardTransactionsTotals

This method take care of computing the totals based on the transactions and the region


  • getShippingMethodsTotals

This method accept a collection of shippingMethods as well as some options

  • includeTax which only enforce the tax_lines to exist either provided by the method itself or the ones that will be queried internally through the tax provider service if useExistingTaxLines is not set to true
  • discounts
  • calculationContext which is the usual calculation context
  • taxRate which is only there to support backward compatibility. I choose to keep it but the methods have been separated
  • useExistingTaxLines which enforce the usage of the tax lines from the method. Can be useful in cases where
    the tax_lines already exists or have been already fetched and assigned by the consumer in order to not re fetch them if
    it is not necessary

This method is of a higher rank as it will only take care of using the right tax lines and call another method
to compute the totals of each method.

To compute the totals of each method there is now two methods which are described bellow

  • getShippingMethodTotalsLegacy

As the name describe, this method calcul the totals for the legacy backward compatibility cases where the taxRate is
explicitly provided to be used. It is normally in the case of the order.

  • getShippingMethodTotals

Which is used to calculate the totals with the new approach using the tax lines.
In that method the options includeTax as been kept only to throw if no tax lines are provided by any of the
possible way, either from the method or explicitly provided


Cart completion

The main purpose of the previous improvements and refactoring was to improve the overall performances
of the cart completion flow. To achieve that, multiple changes needed to be made and will be described bellow.

Cart service and Order service

Most of the changes in the service are separated in two categories

  • Methods signature and refactoring
  • Improvements of the decorate totals method

Some of the method was always expecting a cart id and then was querying the expected cart. In some cases
we are already holding the cart and it make sense that we have the flexibility to provide this cart
instead of fetching it again, expect in those cases where we are not sure what to provide and therefore
we prefer giving the hand to the method to fetch if with the appropriate relations. Therefore for some of the
service methods it is now possible to either give and id or the entity directly. For the later case it
is much more for the people in need of performance improvement and in that case it is the consumer who must
be sure to pass the entity with the appropriate relations.

Finally, the decorateTotals had been reworked in order to provide a better readability, understandability and performances.
To do so, the hidden quadratic and cubic loops have been replaces by the usage of map or object and the overall
loops have been simplified or reduced. We have therefore remove O(n^(2 or 3)) + XO(n) by only XO(n) where X is inferior
to what it was before. Also, we now take advantage of being able to query the tax lines or use the existing one
before calculating the total which gives more flexibility and reduce the number of time we rely on an
external party. For the example, for a cart with 4 items we have now few calls to the external party instead of 64 for the overall flow.
Before those changes, the number a call was constantly increasing with the number of item in the cart, it is not
the case anymore.

The overall decorate totals of the order service have also been improved the same way the cart has been improved and therefore
the readability, understandability and performances have been improved.

Summary

Some other adjustments have been made along the way in order to improve the usability and simplify the usage of
all the changes and open the door to more refactoring (but simpler) in the entire code base where we are relying
on the totals, cart and order. Therefore, future PR's will be open to tackle those refactoring and align the code base
to move toward the new ways of calculating the totals and the usage of the new api's. It will increase the overall
performances of everything that is related to the cart or the order. It should be taken into consideration
that the future changes will probably also impact the payment provider if they rely on one of the entities
mention above. Also, the actual totals service could potentially be deprecated until a certain period of time
in favour of the new approached.

FIXES CORE-327

@changeset-bot
Copy link

changeset-bot bot commented Oct 20, 2022

⚠️ No Changeset found

Latest commit: 3a0f313

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dwene
Copy link
Contributor

dwene commented Oct 20, 2022

Woooo, I'm excited to try this out tomorrow! Can you try adding a similar thing with the tax_lines for OrderService::decorateTotals also? I'm seeing some long non-database performance times listing orders as well. Thanks!

@adrien2p adrien2p closed this Oct 20, 2022
@adrien2p adrien2p reopened this Oct 20, 2022
@adrien2p adrien2p marked this pull request as ready for review October 20, 2022 12:43
@adrien2p adrien2p requested a review from a team as a code owner October 20, 2022 12:43
@dwene
Copy link
Contributor

dwene commented Oct 22, 2022

Man, this is awesome, checkout cart went from 10 seconds to 2 seconds!

Copy link
Contributor

@dwene dwene left a comment

Choose a reason for hiding this comment

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

Left a couple of small comments. I tested it using medusa-dev and everything seems to work correctly and fast 🚀!

packages/medusa/src/strategies/cart-completion.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
@adrien2p adrien2p force-pushed the feat/totals-improvements branch 4 times, most recently from c900531 to 73f8cd8 Compare November 2, 2022 17:08
packages/medusa/src/services/cart.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/cart.ts Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/order.ts Show resolved Hide resolved
packages/medusa/src/services/order.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/totals-new.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@srindom srindom left a comment

Choose a reason for hiding this comment

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

A few more fixes and we should be ready to go 👍

packages/medusa/src/services/new-totals.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/new-totals.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/order.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/payment-provider.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/order.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@srindom srindom left a comment

Choose a reason for hiding this comment

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

Looks good - a few tests and we can merge :)

@adrien2p adrien2p force-pushed the feat/totals-improvements branch 2 times, most recently from 1ae63fc to b579316 Compare November 9, 2022 09:43
@adrien2p
Copy link
Member Author

@srindom @olivermrbl

  • I ve added the new unit tests suite for the new totals service (this is why the PR look enormous now, a lot of tests 😹).
  • I have removed the notion of useExistingTaxLines in order to simplify the api usage. Since the getTaxLines is now properly manage it does not add a lot of overhead so it is a trade off.
  • I have re applied the changes made to the get-order end point and cleaned up the legacy decorate totals
  • various clean up
  • I did add some todo for the places where we are using entire entities in the creation process which can lead to errors with cascade insert if some data should not be inserted but are present (tax lines on the items for example)

I suggest to re review the PR just to be sure :)

packages/medusa/src/services/cart.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/cart.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/cart.ts Outdated Show resolved Hide resolved
packages/medusa/src/strategies/cart-completion.ts Outdated Show resolved Hide resolved
packages/medusa/src/strategies/cart-completion.ts Outdated Show resolved Hide resolved
packages/medusa/src/services/swap.ts Show resolved Hide resolved
packages/medusa/src/services/cart.ts Show resolved Hide resolved
@olivermrbl
Copy link
Contributor

@srindom Do you have any more comments on this one? Let us get it merged, deployed to staging, and tested asap 💪

Copy link
Collaborator

@srindom srindom left a comment

Choose a reason for hiding this comment

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

LGTM!

@olivermrbl olivermrbl merged commit d2b1848 into develop Nov 14, 2022
@olivermrbl olivermrbl deleted the feat/totals-improvements branch November 14, 2022 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants