From d91acbe552375ce794e97894644afe7851ca201f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= Date: Fri, 8 Mar 2019 23:20:21 +0100 Subject: [PATCH 1/3] 18752: make root cause visible for exception on submitQuote Github Issue: https://github.com/magento/magento2/issues/18752 If an exceptions happens in orderManagement->place($order) or an "sales_model_service_quote_submit_success" observer, the catch block itself fires an event that currently fails for guest checkouts in Magento\CatalogInventory\Model\ResourceModel\Stock->correctItemsQty(). This second exception hides the root exception and is logged to the exception log with the message "Rolled back transaction has not been completed correctly". This is not bound for this observer, but may occur in every other observer that is currently register or may be registered in the future. Therefore the failure event is wrapped in a try-catch itself and throws a combined exception that is logged in the exception.log. --- .../Magento/Quote/Model/QuoteManagement.php | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index e21ae7fa1af37..085a0a74bf759 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -12,6 +12,7 @@ use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\StateException; +use Magento\Framework\Phrase; use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Model\Quote\Address\ToOrder as ToOrderConverter; use Magento\Quote\Model\Quote\Address\ToOrderAddress as ToOrderAddressConverter; @@ -529,19 +530,31 @@ protected function submitQuote(QuoteEntity $quote, $orderData = []) ); $this->quoteRepository->save($quote); } catch (\Exception $e) { - if (!empty($this->addressesToSync)) { - foreach ($this->addressesToSync as $addressId) { - $this->addressRepository->deleteById($addressId); + try { + if (!empty($this->addressesToSync)) { + foreach ($this->addressesToSync as $addressId) { + $this->addressRepository->deleteById($addressId); + } } + $this->eventManager->dispatch( + 'sales_model_service_quote_submit_failure', + [ + 'order' => $order, + 'quote' => $quote, + 'exception' => $e, + ] + ); + } catch (\Exception $consecutiveException) { + $message = new Phrase( + "An exception occurred on 'sales_model_service_quote_submit_failure' event: %1\n%2", + [ + $consecutiveException->getMessage(), + $consecutiveException->getTraceAsString() + ] + ); + + throw new LocalizedException($message, $e); } - $this->eventManager->dispatch( - 'sales_model_service_quote_submit_failure', - [ - 'order' => $order, - 'quote' => $quote, - 'exception' => $e - ] - ); throw $e; } return $order; From 91410778d09b45bd2582683b88ff6169ac7898eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= Date: Mon, 11 Mar 2019 15:48:37 +0100 Subject: [PATCH 2/3] amend consecutive exception handling - support masking of root cause in frontend - remove stack trace for consecutive exception to comply to default behaviour --- app/code/Magento/Quote/Model/QuoteManagement.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index 085a0a74bf759..b959dddf550ba 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -12,7 +12,6 @@ use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\StateException; -use Magento\Framework\Phrase; use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Model\Quote\Address\ToOrder as ToOrderConverter; use Magento\Quote\Model\Quote\Address\ToOrderAddress as ToOrderAddressConverter; @@ -545,15 +544,12 @@ protected function submitQuote(QuoteEntity $quote, $orderData = []) ] ); } catch (\Exception $consecutiveException) { - $message = new Phrase( - "An exception occurred on 'sales_model_service_quote_submit_failure' event: %1\n%2", - [ - $consecutiveException->getMessage(), - $consecutiveException->getTraceAsString() - ] + $message = sprintf( + "An exception occurred on 'sales_model_service_quote_submit_failure' event: %s", + $consecutiveException->getMessage() ); - throw new LocalizedException($message, $e); + throw new \Exception($message, 0, $e); } throw $e; } From 0168b1fdda9ab5ae770fb69ee519948a0529fd18 Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Mon, 25 Mar 2019 14:58:00 +0200 Subject: [PATCH 3/3] Fix static tests. --- .../Magento/Quote/Model/QuoteManagement.php | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index b959dddf550ba..1ebf637706dd3 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -529,28 +529,7 @@ protected function submitQuote(QuoteEntity $quote, $orderData = []) ); $this->quoteRepository->save($quote); } catch (\Exception $e) { - try { - if (!empty($this->addressesToSync)) { - foreach ($this->addressesToSync as $addressId) { - $this->addressRepository->deleteById($addressId); - } - } - $this->eventManager->dispatch( - 'sales_model_service_quote_submit_failure', - [ - 'order' => $order, - 'quote' => $quote, - 'exception' => $e, - ] - ); - } catch (\Exception $consecutiveException) { - $message = sprintf( - "An exception occurred on 'sales_model_service_quote_submit_failure' event: %s", - $consecutiveException->getMessage() - ); - - throw new \Exception($message, 0, $e); - } + $this->rollbackAddresses($quote, $order, $e); throw $e; } return $order; @@ -617,4 +596,41 @@ protected function _prepareCustomerQuote($quote) $shipping->setIsDefaultBilling(true); } } + + /** + * Remove related to order and quote addresses and submit exception to further processing. + * + * @param Quote $quote + * @param \Magento\Sales\Api\Data\OrderInterface $order + * @param \Exception $e + * @throws \Exception + */ + private function rollbackAddresses( + QuoteEntity $quote, + \Magento\Sales\Api\Data\OrderInterface $order, + \Exception $e + ): void { + try { + if (!empty($this->addressesToSync)) { + foreach ($this->addressesToSync as $addressId) { + $this->addressRepository->deleteById($addressId); + } + } + $this->eventManager->dispatch( + 'sales_model_service_quote_submit_failure', + [ + 'order' => $order, + 'quote' => $quote, + 'exception' => $e, + ] + ); + } catch (\Exception $consecutiveException) { + $message = sprintf( + "An exception occurred on 'sales_model_service_quote_submit_failure' event: %s", + $consecutiveException->getMessage() + ); + + throw new \Exception($message, 0, $e); + } + } }