【发布时间】:2020-05-31 12:11:48
【问题描述】:
在高负载下(进行负载测试以测试结帐过程)时,我们的自定义订单控制器似乎在付款时抛出异常。这发生在大约九分之一的订单上:
RaceConditionException: "Operated entity was previously modified."
我们已经覆盖了 sylius_shop_checkout_complete 路线,如下所示
sylius_shop_checkout_complete:
path: /complete
methods: [GET, PUT]
defaults:
_controller: sylius.controller.order:completeSectionAction
_sylius:
event: complete
flash: false
template: "@SyliusShop/Checkout/complete.html.twig"
repository:
method: findCartForSummary
arguments:
- "expr:service('sylius.context.cart').getCart().getId()"
state_machine:
graph: sylius_order_checkout
transition: complete
redirect:
route: sylius_shop_order_pay
parameters:
tokenValue: resource.tokenValue
form:
type: Sylius\Bundle\CoreBundle\Form\Type\Checkout\CompleteType
options:
validation_groups: 'sylius_checkout_complete'
还有我们自己的check payment status route,PaymentGateway在付款后重定向到的,如下:
sylius_shop_checkout_status:
path: /check-status
methods: [GET, PUT]
defaults:
_controller: sylius.controller.order:checkStatusAction
_sylius:
event: complete
flash: false
template: "@SyliusShop/Checkout/complete.html.twig"
repository:
method: findCartForSummary
arguments:
- "expr:service('sylius.context.cart').getCart().getId()"
state_machine:
graph: sylius_order_checkout
transition: complete
redirect:
route: sylius_shop_order_pay
parameters:
tokenValue: resource.tokenValue
form:
type: Sylius\Bundle\CoreBundle\Form\Type\Checkout\CompleteType
options:
validation_groups: 'sylius_checkout_complete'
在 checkStatusAction 函数中,我们得到以下异常
request.CRITICAL: Uncaught PHP Exception Sylius\Component\Resource\Exception\RaceConditionException: "Operated entity was previously modified." at /srv/sylius/vendor/sylius/sylius/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/Handler/ResourceUpdateHandler.php line 46 {"exception":"[object] (Sylius\\Component\\Resource\\Exception\\RaceConditionException(code: 0): Operated entity was previously modified. at /srv/sylius/vendor/sylius/sylius/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/Handler/ResourceUpdateHandler.php:46, Doctrine\\ORM\\OptimisticLockException(code: 0): The optimistic lock on an entity failed. at /srv/sylius/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php:64)"} []
这是我们的 checkStatus 函数:
public function checkStatusAction(Request $request, LoggerInterface $logger): Response
{
$configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
$this->isGrantedOr403($configuration, ResourceActions::UPDATE);
$resource = $this->findOr404($configuration);
$form = $this->resourceFormFactory->create($configuration, $resource);
$payment = $resource->getLastPayment();
$paymentMethod = $payment->getMethod();
$paymentConfig = $paymentMethod->getGatewayConfig()->getConfig();
$paymentFactoryName = $paymentMethod->getGatewayConfig()->getFactoryName();
$response = $this->checkPaymentStatus($request->get('resourcePath'), $resource, $paymentConfig);
$decodedResponse = json_decode($response, true);
if(substr($decodedResponse['result']['code'], 0, 4 ) === '000.') {
// If need to run scheduler
$tcResponse = null;
if ($paymentFactoryName === 'tp_payment_subscription' || $paymentFactoryName === 'tp_bank_transfer') {
$amount = $paymentFactoryName === 'tp_bank_transfer' ? 0.00 : number_format($resource->getTotal() / 100, 2, '.', '');
$tcResponse = $this->createSubscription($resource, $response, $amount, $paymentConfig);
}
// Store payment details
$paymentDetails = [
'PayOn' => $response,
'TotalControl' => $tcResponse
];
$payment->setDetails($paymentDetails);
$payment->setState(Payment::STATE_COMPLETED);
try {
$this->resourceUpdateHandler->handle($resource, $configuration, $this->manager);
} catch (UpdateHandlingException $exception) {
if (!$configuration->isHtmlRequest()) {
return $this->viewHandler->handle(
$configuration,
View::create($form, $exception->getApiResponseCode())
);
}
$this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
return $this->redirectHandler->redirectToReferer($configuration);
}
// if ($configuration->isHtmlRequest()) {
// $this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
// }
$postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
return $this->redirectHandler->redirectToResource($configuration, $resource);
}
$this->flashHelper->addErrorFlash($configuration, 'something_went_wrong_error');
$flashes = $request->getSession()->getBag('flashes');
$flashes->add('error', [
'message' => 'sylius.totalp.payment_failure',
'parameters' => ['hello' => 'hi']
]);
return $this->redirectHandler->redirectToReferer($configuration, $resource);
}
错误具体发生在以下行:
$this->resourceUpdateHandler->handle($resource, $configuration, $this->manager);
只有当网站同时发生多个订单时才会出现此问题,有人知道如何解决此问题吗?
【问题讨论】: