Skip to content

Commit 4328261

Browse files
committed
Merge branch 'MC-42025' of https://github.com/magento-l3/magento2ce into TANGO_PR-05-11-2021_24
2 parents ac232c8 + 7b83b54 commit 4328261

File tree

5 files changed

+319
-42
lines changed

5 files changed

+319
-42
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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\Grid;
9+
10+
use Magento\Framework\App\CacheInterface;
11+
12+
/**
13+
* Cache for last grid update time.
14+
*/
15+
class LastUpdateTimeCache
16+
{
17+
/**
18+
* Prefix for cache key.
19+
*/
20+
private const CACHE_PREFIX = 'LAST_GRID_UPDATE_TIME';
21+
22+
/**
23+
* @var CacheInterface
24+
*/
25+
private $cache;
26+
27+
/**
28+
* @param CacheInterface $cache
29+
*/
30+
public function __construct(CacheInterface $cache)
31+
{
32+
$this->cache = $cache;
33+
}
34+
35+
/**
36+
* Save last grid update time.
37+
*
38+
* @param string $gridTableName
39+
* @param string $lastUpdatedAt
40+
* @return void
41+
*/
42+
public function save(string $gridTableName, string $lastUpdatedAt): void
43+
{
44+
$this->cache->save(
45+
$lastUpdatedAt,
46+
$this->getCacheKey($gridTableName),
47+
[],
48+
3600
49+
);
50+
}
51+
52+
/**
53+
* Get last grid update time.
54+
*
55+
* @param string $gridTableName
56+
* @return string|null
57+
*/
58+
public function get(string $gridTableName): ?string
59+
{
60+
$lastUpdatedAt = $this->cache->load($this->getCacheKey($gridTableName));
61+
62+
return $lastUpdatedAt ?: null;
63+
}
64+
65+
/**
66+
* Remove last grid update time.
67+
*
68+
* @param string $gridTableName
69+
* @return void
70+
*/
71+
public function remove(string $gridTableName): void
72+
{
73+
$this->cache->remove($this->getCacheKey($gridTableName));
74+
}
75+
76+
/**
77+
* Generate cache key.
78+
*
79+
* @param string $gridTableName
80+
* @return string
81+
*/
82+
private function getCacheKey(string $gridTableName): string
83+
{
84+
return self::CACHE_PREFIX . ':' . $gridTableName;
85+
}
86+
}

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
use Magento\Framework\App\ObjectManager;
99
use Magento\Framework\DB\Adapter\AdapterInterface;
1010
use Magento\Framework\Model\ResourceModel\Db\Context;
11+
use Magento\Sales\Model\Grid\LastUpdateTimeCache;
1112
use Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProviderInterface;
1213

1314
/**
14-
* Class Grid
15+
* Sales order grid resource model.
1516
*/
1617
class Grid extends AbstractGrid
1718
{
@@ -45,6 +46,11 @@ class Grid extends AbstractGrid
4546
*/
4647
private $notSyncedDataProvider;
4748

49+
/**
50+
* @var LastUpdateTimeCache
51+
*/
52+
private $lastUpdateTimeCache;
53+
4854
/**
4955
* Order grid rows batch size
5056
*/
@@ -58,7 +64,8 @@ class Grid extends AbstractGrid
5864
* @param array $joins
5965
* @param array $columns
6066
* @param string $connectionName
61-
* @param NotSyncedDataProviderInterface $notSyncedDataProvider
67+
* @param NotSyncedDataProviderInterface|null $notSyncedDataProvider
68+
* @param LastUpdateTimeCache|null $lastUpdateTimeCache
6269
*/
6370
public function __construct(
6471
Context $context,
@@ -68,15 +75,19 @@ public function __construct(
6875
array $joins = [],
6976
array $columns = [],
7077
$connectionName = null,
71-
NotSyncedDataProviderInterface $notSyncedDataProvider = null
78+
NotSyncedDataProviderInterface $notSyncedDataProvider = null,
79+
LastUpdateTimeCache $lastUpdateTimeCache = null
7280
) {
7381
$this->mainTableName = $mainTableName;
7482
$this->gridTableName = $gridTableName;
7583
$this->orderIdField = $orderIdField;
7684
$this->joins = $joins;
7785
$this->columns = $columns;
78-
$this->notSyncedDataProvider =
79-
$notSyncedDataProvider ?: ObjectManager::getInstance()->get(NotSyncedDataProviderInterface::class);
86+
$this->notSyncedDataProvider = $notSyncedDataProvider ??
87+
ObjectManager::getInstance()->get(NotSyncedDataProviderInterface::class);
88+
$this->lastUpdateTimeCache = $lastUpdateTimeCache ??
89+
ObjectManager::getInstance()->get(LastUpdateTimeCache::class);
90+
8091
parent::__construct($context, $connectionName);
8192
}
8293

@@ -118,6 +129,7 @@ public function refresh($value, $field = null)
118129
*/
119130
public function refreshBySchedule()
120131
{
132+
$lastUpdatedAt = null;
121133
$notSyncedIds = $this->notSyncedDataProvider->getIds($this->mainTableName, $this->gridTableName);
122134
foreach (array_chunk($notSyncedIds, self::BATCH_SIZE) as $bunch) {
123135
$select = $this->getGridOriginSelect()->where($this->mainTableName . '.entity_id IN (?)', $bunch);
@@ -127,6 +139,15 @@ public function refreshBySchedule()
127139
$fetchResult,
128140
array_keys($this->columns)
129141
);
142+
143+
$timestamps = array_column($fetchResult, 'updated_at');
144+
if ($timestamps) {
145+
$lastUpdatedAt = max(max($timestamps), $lastUpdatedAt);
146+
}
147+
}
148+
149+
if ($lastUpdatedAt) {
150+
$this->lastUpdateTimeCache->save($this->gridTableName, $lastUpdatedAt);
130151
}
131152
}
132153

app/code/Magento/Sales/Model/ResourceModel/Provider/UpdatedAtListProvider.php

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use Magento\Framework\App\ResourceConnection;
99
use Magento\Framework\DB\Adapter\AdapterInterface;
10+
use Magento\Sales\Model\Grid\LastUpdateTimeCache;
1011

1112
/**
1213
* Retrieves ID's of not synced by `updated_at` column entities.
@@ -25,36 +26,42 @@ class UpdatedAtListProvider implements NotSyncedDataProviderInterface
2526
*/
2627
private $connection;
2728

29+
/**
30+
* @var LastUpdateTimeCache
31+
*/
32+
private $lastUpdateTimeCache;
33+
2834
/**
2935
* @param ResourceConnection $resourceConnection
36+
* @param LastUpdateTimeCache $lastUpdateTimeCache
3037
*/
31-
public function __construct(ResourceConnection $resourceConnection)
32-
{
38+
public function __construct(
39+
ResourceConnection $resourceConnection,
40+
LastUpdateTimeCache $lastUpdateTimeCache
41+
) {
3342
$this->connection = $resourceConnection->getConnection('sales');
3443
$this->resourceConnection = $resourceConnection;
44+
$this->lastUpdateTimeCache = $lastUpdateTimeCache;
3545
}
3646

3747
/**
3848
* @inheritdoc
3949
*/
4050
public function getIds($mainTableName, $gridTableName)
4151
{
42-
$mainTableName = $this->resourceConnection->getTableName($mainTableName);
43-
$gridTableName = $this->resourceConnection->getTableName($gridTableName);
4452
$select = $this->connection->select()
45-
->from($mainTableName, [$mainTableName . '.entity_id'])
53+
->from(['main_table' => $this->resourceConnection->getTableName($mainTableName)], ['main_table.entity_id'])
4654
->joinInner(
47-
[$gridTableName => $gridTableName],
48-
sprintf(
49-
'%s.entity_id = %s.entity_id AND %s.updated_at > %s.updated_at',
50-
$mainTableName,
51-
$gridTableName,
52-
$mainTableName,
53-
$gridTableName
54-
),
55+
['grid_table' => $this->resourceConnection->getTableName($gridTableName)],
56+
'main_table.entity_id = grid_table.entity_id AND main_table.updated_at > grid_table.updated_at',
5557
[]
5658
);
5759

60+
$lastUpdatedAt = $this->lastUpdateTimeCache->get($gridTableName);
61+
if ($lastUpdatedAt) {
62+
$select->where('main_table.updated_at > ?', $lastUpdatedAt);
63+
}
64+
5865
return $this->connection->fetchAll($select, [], \Zend_Db::FETCH_COLUMN);
5966
}
6067
}

app/code/Magento/Sales/Test/Unit/Model/ResourceModel/GridTest.php

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\DB\Adapter\AdapterInterface as ConnectionAdapterInterface;
1111
use Magento\Framework\DB\Select;
1212
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
13+
use Magento\Sales\Model\Grid\LastUpdateTimeCache;
1314
use Magento\Sales\Model\ResourceModel\Grid;
1415
use Magento\Sales\Model\ResourceModel\Provider\NotSyncedDataProviderInterface;
1516
use PHPUnit\Framework\MockObject\MockObject;
@@ -35,6 +36,11 @@ class GridTest extends TestCase
3536
*/
3637
private $connection;
3738

39+
/**
40+
* @var LastUpdateTimeCache|MockObject
41+
*/
42+
private $lastUpdateTimeCache;
43+
3844
/**
3945
* @var string
4046
*/
@@ -49,8 +55,9 @@ class GridTest extends TestCase
4955
* @var array
5056
*/
5157
private $columns = [
52-
'column_1_key' => 'column_1_value',
53-
'column_2_key' => 'column_2_value'
58+
'entity_id' => 'sales_order.entity_id',
59+
'status' => 'sales_order.status',
60+
'updated_at' => 'sales_order.updated_at',
5461
];
5562

5663
/**
@@ -59,14 +66,9 @@ class GridTest extends TestCase
5966
protected function setUp(): void
6067
{
6168
$objectManager = new ObjectManager($this);
62-
$this->notSyncedDataProvider = $this->getMockBuilder(NotSyncedDataProviderInterface::class)
63-
->disableOriginalConstructor()
64-
->setMethods(['getIds'])
65-
->getMockForAbstractClass();
66-
$this->connection = $this->getMockBuilder(ConnectionAdapterInterface::class)
67-
->disableOriginalConstructor()
68-
->setMethods(['select', 'fetchAll', 'insertOnDuplicate'])
69-
->getMockForAbstractClass();
69+
$this->notSyncedDataProvider = $this->createMock(NotSyncedDataProviderInterface::class);
70+
$this->connection = $this->createMock(ConnectionAdapterInterface::class);
71+
$this->lastUpdateTimeCache = $this->createMock(LastUpdateTimeCache::class);
7072

7173
$this->grid = $objectManager->getObject(
7274
Grid::class,
@@ -76,7 +78,8 @@ protected function setUp(): void
7678
'gridTableName' => $this->gridTable,
7779
'connection' => $this->connection,
7880
'_tables' => ['sales_order' => $this->mainTable, 'sales_order_grid' => $this->gridTable],
79-
'columns' => $this->columns
81+
'columns' => $this->columns,
82+
'lastUpdateTimeCache' => $this->lastUpdateTimeCache,
8083
]
8184
);
8285
}
@@ -87,26 +90,49 @@ protected function setUp(): void
8790
public function testRefreshBySchedule()
8891
{
8992
$notSyncedIds = ['1', '2', '3'];
90-
$fetchResult = ['column_1' => '1', 'column_2' => '2'];
91-
92-
$this->notSyncedDataProvider->expects($this->atLeastOnce())->method('getIds')->willReturn($notSyncedIds);
93-
$select = $this->getMockBuilder(Select::class)
94-
->disableOriginalConstructor()
95-
->setMethods(['from', 'columns', 'where'])
96-
->getMock();
97-
$select->expects($this->atLeastOnce())->method('from')->with(['sales_order' => $this->mainTable], [])
93+
$fetchResult = [];
94+
for ($i = 1; $i <= 220; $i++) {
95+
$fetchResult[] = [
96+
'entity_id' => $i,
97+
'status' => 1,
98+
'updated_at' => '2021-01-01 01:02:03',
99+
];
100+
}
101+
$fetchResult[50]['updated_at'] = '2021-02-03 01:02:03';
102+
$fetchResult[150]['updated_at'] = '2021-03-04 01:02:03';
103+
104+
$this->notSyncedDataProvider->expects($this->atLeastOnce())
105+
->method('getIds')
106+
->willReturn($notSyncedIds);
107+
$select = $this->createMock(Select::class);
108+
$select->expects($this->atLeastOnce())
109+
->method('from')
110+
->with(['sales_order' => $this->mainTable], [])
111+
->willReturnSelf();
112+
$select->expects($this->atLeastOnce())
113+
->method('columns')
98114
->willReturnSelf();
99-
$select->expects($this->atLeastOnce())->method('columns')->willReturnSelf();
100-
$select->expects($this->atLeastOnce())->method('where')
115+
$select->expects($this->atLeastOnce())
116+
->method('where')
101117
->with($this->mainTable . '.entity_id IN (?)', $notSyncedIds)
102118
->willReturnSelf();
103119

104-
$this->connection->expects($this->atLeastOnce())->method('select')->willReturn($select);
105-
$this->connection->expects($this->atLeastOnce())->method('fetchAll')->with($select)->willReturn($fetchResult);
106-
$this->connection->expects($this->atLeastOnce())->method('insertOnDuplicate')
120+
$this->connection->expects($this->atLeastOnce())
121+
->method('select')
122+
->willReturn($select);
123+
$this->connection->expects($this->atLeastOnce())
124+
->method('fetchAll')
125+
->with($select)
126+
->willReturn($fetchResult);
127+
$this->connection->expects($this->atLeastOnce())
128+
->method('insertOnDuplicate')
107129
->with($this->gridTable, $fetchResult, array_keys($this->columns))
108130
->willReturn(array_count_values($notSyncedIds));
109131

132+
$this->lastUpdateTimeCache->expects($this->once())
133+
->method('save')
134+
->with($this->gridTable, '2021-03-04 01:02:03');
135+
110136
$this->grid->refreshBySchedule();
111137
}
112138
}

0 commit comments

Comments
 (0)