Skip to content

Quote Attribute trigger_recollect causes a timeout #9580

Closed
@bh-ref

Description

@bh-ref

Preconditions

  1. Magento CE 2.1.5
  2. MariaDB 10.1.20
  3. PHP 7.0.14

Steps to reproduce

  1. We created a custom shipping carrier. This shipping carrier implements the method
    public function collectRates(RateRequest $request).
  2. Log in as a customer.
  3. Add some products to your quote.
  4. Do not go to checkout. Log off.
  5. Change some product and/or catalog price rules which affect the products in the quote from step 2. This should set the attribute trigger_recollect to 1 (integer) for that quote because of
    \Magento\Sales\Observer\Backend\CatalogProductSaveAfterObserver::execute() and
    \Magento\Sales\Observer\Backend\CatalogPriceRule::execute().
  6. If you now log back in as a customer, your previous quote will be loaded.
  7. If you then add a product, the shipping rate from our custom shipping carrier will be collected. We use \Magento\Checkout\Model\Cart::getQuote() to do some checks. \Magento\Quote\Model\Quote::_afterLoad() will eventually be triggered, which calls \Magento\Quote\Model\Quote::collectTotals() if the attribute trigger_recollect is set to 1.
  8. Now, things begin to repeat because the rates for our custom shipping carrier are collected again.
  9. A timeout appears because of this loop.
  10. The customer cannot open any other page on the website, because this cycle continues for that customer. After waiting for the page to finish loading, all the customer will see in the end is a HTTP error 503.

Expected result

  1. The attribute trigger_recollect in a quote should be set to 0 (integer) at some time.

Actual result

  1. In all the magento code, I could only see the attribute trigger_recollect in a quote being set to 1, but never back to 0.

My patch, which seems to work fine, is:
In \Magento\Quote\Model\Quote::_afterLoad() add a reset of the attribute trigger_recollect after collecting the totals:

    protected function _afterLoad()
    {
        // collect totals and save me, if required
        if (1 == $this->getData('trigger_recollect')) {
            $this
                ->collectTotals()
                ->setTriggerRecollect(0) // patch: reset the attribute trigger_recollect
                ->save();
        }
        return parent::_afterLoad();
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fixed in 2.1.xThe issue has been fixed in 2.1 release lineFixed in 2.2.xThe issue has been fixed in 2.2 release lineFixed in 2.3.xThe issue has been fixed in 2.3 release lineIssue: Clear DescriptionGate 2 Passed. Manual verification of the issue description passedIssue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedIssue: Format is validGate 1 Passed. Automatic verification of issue format passedReproduced on 2.1.xThe issue has been reproduced on latest 2.1 release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions