Skip to content

Commit 0a52f88

Browse files
authored
Merge pull request #2743 from magento-panda/PANDA-PR-2.2
Fixed issues: - MAGETWO-89238: [Sales email] Disabled invoice emails produce performance issue - MAGETWO-75530: Deadlock when 'Asynchronous indexing' is enabled (insert from select on sales_order_grid).
2 parents c1eb14b + dbccfa9 commit 0a52f88

File tree

42 files changed

+649
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+649
-157
lines changed

app/code/Magento/Backend/Controller/Adminhtml/System/Store/DeleteStorePost.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ public function execute()
3737
try {
3838
$model->delete();
3939

40-
$this->_eventManager->dispatch('store_delete', ['store' => $model]);
41-
4240
$this->messageManager->addSuccess(__('You deleted the store view.'));
4341
return $redirectResult->setPath('adminhtml/*/');
4442
} catch (\Magento\Framework\Exception\LocalizedException $e) {

app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ private function processWebsiteSave($postData)
4646
*/
4747
private function processStoreSave($postData)
4848
{
49-
$eventName = 'store_edit';
5049
/** @var \Magento\Store\Model\Store $storeModel */
5150
$storeModel = $this->_objectManager->create(\Magento\Store\Model\Store::class);
5251
$postData['store']['name'] = $this->filterManager->removeTags($postData['store']['name']);
@@ -56,7 +55,6 @@ private function processStoreSave($postData)
5655
$storeModel->setData($postData['store']);
5756
if ($postData['store']['store_id'] == '') {
5857
$storeModel->setId(null);
59-
$eventName = 'store_add';
6058
}
6159
$groupModel = $this->_objectManager->create(
6260
\Magento\Store\Model\Group::class
@@ -70,8 +68,6 @@ private function processStoreSave($postData)
7068
);
7169
}
7270
$storeModel->save();
73-
$this->_objectManager->get(\Magento\Store\Model\StoreManager::class)->reinitStores();
74-
$this->_eventManager->dispatch($eventName, ['store' => $storeModel]);
7571
$this->messageManager->addSuccess(__('You saved the store view.'));
7672

7773
return $postData;
@@ -102,7 +98,6 @@ private function processGroupSave($postData)
10298
);
10399
}
104100
$groupModel->save();
105-
$this->_eventManager->dispatch('store_group_save', ['group' => $groupModel]);
106101
$this->messageManager->addSuccess(__('You saved the store.'));
107102

108103
return $postData;

app/code/Magento/Sales/Model/EmailSenderHandler.php

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
namespace Magento\Sales\Model;
77

8+
use Magento\Sales\Model\Order\Email\Container\IdentityInterface;
9+
810
/**
911
* Sales emails sending
1012
*
@@ -41,22 +43,41 @@ class EmailSenderHandler
4143
*/
4244
protected $globalConfig;
4345

46+
/**
47+
* @var IdentityInterface
48+
*/
49+
private $identityContainer;
50+
51+
/**
52+
* @var \Magento\Store\Model\StoreManagerInterface
53+
*/
54+
private $storeManager;
55+
4456
/**
4557
* @param \Magento\Sales\Model\Order\Email\Sender $emailSender
4658
* @param \Magento\Sales\Model\ResourceModel\EntityAbstract $entityResource
4759
* @param \Magento\Sales\Model\ResourceModel\Collection\AbstractCollection $entityCollection
4860
* @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig
61+
* @param IdentityInterface|null $identityContainer
62+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
4963
*/
5064
public function __construct(
5165
\Magento\Sales\Model\Order\Email\Sender $emailSender,
5266
\Magento\Sales\Model\ResourceModel\EntityAbstract $entityResource,
5367
\Magento\Sales\Model\ResourceModel\Collection\AbstractCollection $entityCollection,
54-
\Magento\Framework\App\Config\ScopeConfigInterface $globalConfig
68+
\Magento\Framework\App\Config\ScopeConfigInterface $globalConfig,
69+
IdentityInterface $identityContainer = null,
70+
\Magento\Store\Model\StoreManagerInterface $storeManager = null
5571
) {
5672
$this->emailSender = $emailSender;
5773
$this->entityResource = $entityResource;
5874
$this->entityCollection = $entityCollection;
5975
$this->globalConfig = $globalConfig;
76+
77+
$this->identityContainer = $identityContainer ?: \Magento\Framework\App\ObjectManager::getInstance()
78+
->get(\Magento\Sales\Model\Order\Email\Container\NullIdentity::class);
79+
$this->storeManager = $storeManager ?: \Magento\Framework\App\ObjectManager::getInstance()
80+
->get(\Magento\Store\Model\StoreManagerInterface::class);
6081
}
6182

6283
/**
@@ -69,14 +90,50 @@ public function sendEmails()
6990
$this->entityCollection->addFieldToFilter('send_email', ['eq' => 1]);
7091
$this->entityCollection->addFieldToFilter('email_sent', ['null' => true]);
7192

72-
/** @var \Magento\Sales\Model\AbstractModel $item */
73-
foreach ($this->entityCollection->getItems() as $item) {
74-
if ($this->emailSender->send($item, true)) {
75-
$this->entityResource->save(
76-
$item->setEmailSent(true)
77-
);
93+
/** @var \Magento\Store\Api\Data\StoreInterface[] $stores */
94+
$stores = $this->getStores(clone $this->entityCollection);
95+
96+
/** @var \Magento\Store\Model\Store $store */
97+
foreach ($stores as $store) {
98+
$this->identityContainer->setStore($store);
99+
if (!$this->identityContainer->isEnabled()) {
100+
continue;
101+
}
102+
$entityCollection = clone $this->entityCollection;
103+
$entityCollection->addFieldToFilter('store_id', $store->getId());
104+
105+
/** @var \Magento\Sales\Model\AbstractModel $item */
106+
foreach ($entityCollection->getItems() as $item) {
107+
if ($this->emailSender->send($item, true)) {
108+
$this->entityResource->save(
109+
$item->setEmailSent(true)
110+
);
111+
}
78112
}
79113
}
80114
}
81115
}
116+
117+
/**
118+
* Get stores for given entities.
119+
*
120+
* @param ResourceModel\Collection\AbstractCollection $entityCollection
121+
* @return \Magento\Store\Api\Data\StoreInterface[]
122+
* @throws \Magento\Framework\Exception\NoSuchEntityException
123+
*/
124+
private function getStores(
125+
\Magento\Sales\Model\ResourceModel\Collection\AbstractCollection $entityCollection
126+
): array {
127+
$stores = [];
128+
129+
$entityCollection->addAttributeToSelect('store_id')->getSelect()->group('store_id');
130+
/** @var \Magento\Sales\Model\EntityInterface $item */
131+
foreach ($entityCollection->getItems() as $item) {
132+
/** @var \Magento\Store\Model\StoreManagerInterface $store */
133+
$store = $this->storeManager->getStore($item->getStoreId());
134+
$stores[$item->getStoreId()] = $store;
135+
}
136+
137+
return $stores;
138+
}
82139
}

app/code/Magento/Sales/Model/Order/Email/Container/IdentityInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
namespace Magento\Sales\Model\Order\Email\Container;
6+
7+
namespace Magento\Sales\Model\Order\Email\Container;
78

89
use Magento\Store\Model\Store;
910

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Sales\Model\Order\Email\Container;
9+
10+
class NullIdentity extends Container implements IdentityInterface
11+
{
12+
/**
13+
* @inheritdoc
14+
*/
15+
public function isEnabled()
16+
{
17+
return true;
18+
}
19+
20+
/**
21+
* @inheritdoc
22+
*/
23+
public function getEmailCopyTo()
24+
{
25+
return false;
26+
}
27+
28+
/**
29+
* @inheritdoc
30+
*/
31+
public function getCopyMethod()
32+
{
33+
return '';
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function getGuestTemplateId()
40+
{
41+
return null;
42+
}
43+
44+
/**
45+
* @inheritdoc
46+
*/
47+
public function getTemplateId()
48+
{
49+
return null;
50+
}
51+
52+
/**
53+
* @inheritdoc
54+
*/
55+
public function getEmailIdentity()
56+
{
57+
return '';
58+
}
59+
}

app/code/Magento/Sales/Model/ResourceModel/Grid.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ class Grid extends AbstractGrid
4545
*/
4646
private $notSyncedDataProvider;
4747

48+
/**
49+
* Order grid rows batch size
50+
*/
51+
const BATCH_SIZE = 100;
52+
4853
/**
4954
* @param Context $context
5055
* @param string $mainTableName
@@ -104,25 +109,20 @@ public function refresh($value, $field = null)
104109
*
105110
* Only orders created/updated since the last method call will be added.
106111
*
107-
* @return \Zend_Db_Statement_Interface
112+
* @return void
108113
*/
109114
public function refreshBySchedule()
110115
{
111-
$select = $this->getGridOriginSelect()
112-
->where(
113-
$this->mainTableName . '.entity_id IN (?)',
114-
$this->notSyncedDataProvider->getIds($this->mainTableName, $this->gridTableName)
116+
$notSyncedIds = $this->notSyncedDataProvider->getIds($this->mainTableName, $this->gridTableName);
117+
foreach (array_chunk($notSyncedIds, self::BATCH_SIZE) as $bunch) {
118+
$select = $this->getGridOriginSelect()->where($this->mainTableName . '.entity_id IN (?)', $bunch);
119+
$fetchResult = $this->getConnection()->fetchAll($select);
120+
$this->getConnection()->insertOnDuplicate(
121+
$this->getTable($this->gridTableName),
122+
$fetchResult,
123+
array_keys($this->columns)
115124
);
116-
117-
return $this->getConnection()->query(
118-
$this->getConnection()
119-
->insertFromSelect(
120-
$select,
121-
$this->getTable($this->gridTableName),
122-
array_keys($this->columns),
123-
AdapterInterface::INSERT_ON_DUPLICATE
124-
)
125-
);
125+
}
126126
}
127127

128128
/**

app/code/Magento/Sales/Model/ResourceModel/GridInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function refresh($value, $field = null);
2929
*
3030
* Only rows created/updated since the last method call should be added.
3131
*
32-
* @return \Zend_Db_Statement_Interface
32+
* @return void
3333
*/
3434
public function refreshBySchedule();
3535

0 commit comments

Comments
 (0)