Skip to content

Commit fa0323e

Browse files
Merge pull request #50 from aligent/feature/convert_temp_table_to_replica
Replace creating/dropping of table with inserting/deleting of records…
2 parents 5a4adf9 + 68ae7ba commit fa0323e

File tree

6 files changed

+172
-149
lines changed

6 files changed

+172
-149
lines changed

src/index/Model/Changelog/InsertRecords.php

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,53 @@
66
use Aligent\FredhopperIndexer\Model\DataHandler;
77
use Aligent\FredhopperIndexer\Model\ResourceModel\Changelog as ChangelogResource;
88
use Magento\Framework\App\ResourceConnection;
9-
use Magento\Framework\Exception\LocalizedException;
109

1110
class InsertRecords
1211
{
1312
/**
1413
* @param ResourceConnection $resourceConnection
1514
* @param ChangelogResource $changelogResource
16-
* @param TempTable $tempTable
1715
*/
1816
public function __construct(
1917
private readonly ResourceConnection $resourceConnection,
2018
private readonly ChangelogResource $changelogResource,
21-
private readonly TempTable $tempTable
2219
) {
2320
}
2421

2522
/**
2623
* Insert add, update and delete records into the changelog table
2724
*
25+
* @param string $replicaId
2826
* @return void
2927
* @throws \Zend_Db_Select_Exception
30-
* @throws LocalizedException
3128
*/
32-
public function execute(): void
29+
public function execute(string $replicaId): void
3330
{
34-
$tempTableName = $this->tempTable->getTempTableName();
3531
$addedProductIds = $this->getAddedOrDeletedProductsByType(
3632
true,
3733
DataHandler::TYPE_PRODUCT,
38-
$tempTableName
34+
$replicaId
3935
);
4036
$addedVariantIds = $this->getAddedOrDeletedProductsByType(
4137
true,
4238
DataHandler::TYPE_VARIANT,
43-
$tempTableName
39+
$replicaId
4440
);
4541
$this->changelogResource->insertAdditionOperations($addedProductIds, $addedVariantIds);
4642

47-
$updatedProductIds = $this->getUpdatedProductsByType(DataHandler::TYPE_PRODUCT, $tempTableName);
48-
$updatedVariantIds = $this->getUpdatedProductsByType(DataHandler::TYPE_VARIANT, $tempTableName);
43+
$updatedProductIds = $this->getUpdatedProductsByType(DataHandler::TYPE_PRODUCT, $replicaId);
44+
$updatedVariantIds = $this->getUpdatedProductsByType(DataHandler::TYPE_VARIANT, $replicaId);
4945
$this->changelogResource->insertUpdateOperations($updatedProductIds, $updatedVariantIds);
5046

5147
$deletedProductIds = $this->getAddedOrDeletedProductsByType(
5248
false,
5349
DataHandler::TYPE_PRODUCT,
54-
$tempTableName
50+
$replicaId
5551
);
5652
$deletedVariantIds = $this->getAddedOrDeletedProductsByType(
5753
false,
5854
DataHandler::TYPE_VARIANT,
59-
$tempTableName
55+
$replicaId
6056
);
6157
$this->changelogResource->insertDeleteOperations($deletedProductIds, $deletedVariantIds);
6258
}
@@ -66,27 +62,41 @@ public function execute(): void
6662
*
6763
* @param bool $isAddition
6864
* @param string $productType
69-
* @param string $tempTableName
65+
* @param string $replicaId
7066
* @return array
7167
*/
7268
private function getAddedOrDeletedProductsByType(
7369
bool $isAddition,
7470
string $productType,
75-
string $tempTableName
71+
string $replicaId
7672
): array {
7773
$connection = $this->resourceConnection->getConnection();
7874
$select = $connection->select();
7975

80-
$select->from(
81-
['main_table' => ($isAddition ? DataHandler::INDEX_TABLE_NAME : $tempTableName)],
82-
['product_id']
83-
);
84-
$select->joinLeft(
85-
['temp_table' => ($isAddition ? $tempTableName : DataHandler::INDEX_TABLE_NAME)],
86-
'temp_table.product_id = main_table.product_id AND '.
87-
'temp_table.product_type = main_table.product_type',
88-
[]
89-
);
76+
if ($isAddition) {
77+
$select->from(
78+
['main_table' => DataHandler::INDEX_TABLE_NAME],
79+
['product_id']
80+
);
81+
$select->joinLeft(
82+
['temp_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME],
83+
'temp_table.product_id = main_table.product_id AND '.
84+
'temp_table.product_type = main_table.product_type AND '.
85+
'temp_table.replica_id = ' . "'" . $replicaId . "'"
86+
);
87+
} else {
88+
$select->from(
89+
['main_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME],
90+
['product_id']
91+
);
92+
$select->joinLeft(
93+
['temp_table' => DataHandler::INDEX_TABLE_NAME],
94+
'temp_table.product_id = main_table.product_id AND '.
95+
'temp_table.product_type = main_table.product_type'
96+
);
97+
$select->where('main_table.replica_id = ?', $replicaId);
98+
}
99+
90100
$select->where('temp_table.product_id is null');
91101
$select->where('main_table.product_type = ?', $productType);
92102
$select->group('main_table.product_id');
@@ -95,20 +105,20 @@ private function getAddedOrDeletedProductsByType(
95105
}
96106

97107
/**
98-
* Determine which products have been updated between the main and temporary table
108+
* Determine which products have been updated between the main and replica table
99109
*
100110
* @param string $productType
101-
* @param string $tempTableName
111+
* @param string $replicaId
102112
* @return array
103113
* @throws \Zend_Db_Select_Exception
104114
*/
105-
private function getUpdatedProductsByType(string $productType, string $tempTableName): array
115+
private function getUpdatedProductsByType(string $productType, string $replicaId): array
106116
{
107117
// get all product ids and variant ids that exist in both tables
108118
// we do not want to consider products that are being added or deleted completely
109119
$connection = $this->resourceConnection->getConnection();
110120
$existingProductsSelect = $connection->select();
111-
$existingProductsSelect->from(['temp_table' => $tempTableName], ['product_id']);
121+
$existingProductsSelect->from(['temp_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME], ['product_id']);
112122
$existingProductsSelect->joinInner(
113123
['main_table' => DataHandler::INDEX_TABLE_NAME],
114124
'main_table.product_id = temp_table.product_id AND ' .
@@ -117,6 +127,7 @@ private function getUpdatedProductsByType(string $productType, string $tempTable
117127
);
118128
$existingProductsSelect->distinct();
119129
$existingProductsSelect->where('temp_table.product_type = ?', $productType);
130+
$existingProductsSelect->where('temp_table.replica_id = ?', $replicaId);
120131
$existingProductIds = $connection->fetchCol($existingProductsSelect);
121132

122133
// records that are in the new table, but not in the old table
@@ -126,10 +137,11 @@ private function getUpdatedProductsByType(string $productType, string $tempTable
126137
['product_id']
127138
);
128139
$existingProductsTempMissingSelect->joinLeft(
129-
['temp_table' => $tempTableName],
140+
['temp_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME],
130141
'main_table.product_id = temp_table.product_id AND ' .
131142
'main_table.product_type = temp_table.product_type AND ' .
132-
'main_table.store_id = temp_table.store_id',
143+
'main_table.store_id = temp_table.store_id AND ' .
144+
'temp_table.replica_id = ' . "'" . $replicaId . "'",
133145
[]
134146
);
135147
$existingProductsTempMissingSelect->where('temp_table.product_id IS NULL');
@@ -139,7 +151,7 @@ private function getUpdatedProductsByType(string $productType, string $tempTable
139151
// records that are in the old table, but not in the new table
140152
$existingProductsMainMissingSelect = $connection->select();
141153
$existingProductsMainMissingSelect->from(
142-
['temp_table' => $tempTableName],
154+
['temp_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME],
143155
['product_id']
144156
);
145157
$existingProductsMainMissingSelect->joinLeft(
@@ -152,6 +164,7 @@ private function getUpdatedProductsByType(string $productType, string $tempTable
152164
$existingProductsMainMissingSelect->where('main_table.product_id IS NULL');
153165
$existingProductsMainMissingSelect->where('temp_table.product_type = ?', $productType);
154166
$existingProductsMainMissingSelect->where('temp_table.product_id in (?)', $existingProductIds);
167+
$existingProductsMainMissingSelect->where('temp_table.replica_id = ?', $replicaId);
155168

156169
// records that differ by parent_id or attribute_data
157170
$existingProductsDifferenceSelect = $connection->select();
@@ -160,10 +173,11 @@ private function getUpdatedProductsByType(string $productType, string $tempTable
160173
['product_id']
161174
);
162175
$existingProductsDifferenceSelect->joinInner(
163-
['temp_table' => $tempTableName],
176+
['temp_table' => ReplicaTableMaintainer::REPLICA_TABLE_NAME],
164177
'main_table.product_id = temp_table.product_id AND ' .
165178
'main_table.product_type = temp_table.product_type AND ' .
166179
'main_table.store_id = temp_table.store_id AND '.
180+
'temp_table.replica_id = ' . "'" . $replicaId . "'" . ' AND ' .
167181
'NOT (main_table.parent_id <=> temp_table.parent_id AND ' .
168182
'main_table.attribute_data <=> temp_table.attribute_data)',
169183
[]
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
namespace Aligent\FredhopperIndexer\Model\Changelog;
5+
6+
use Aligent\FredhopperIndexer\Model\DataHandler;
7+
use Magento\Framework\App\ResourceConnection;
8+
use Random\RandomException;
9+
10+
class ReplicaTableMaintainer
11+
{
12+
13+
public const REPLICA_TABLE_NAME = DataHandler::INDEX_TABLE_NAME . '_replica';
14+
15+
/**
16+
* @param ResourceConnection $resourceConnection
17+
*/
18+
public function __construct(
19+
private readonly ResourceConnection $resourceConnection
20+
) {
21+
}
22+
23+
/**
24+
* Generate a random string of characters to use as an ID when comparing records before/after indexing
25+
*
26+
* @return string
27+
*/
28+
public function generateUniqueId(): string
29+
{
30+
try {
31+
$id = bin2hex(random_bytes(8));
32+
} catch (RandomException) {
33+
$id = uniqid( '',true);
34+
}
35+
return substr($id, 0, 8);
36+
}
37+
38+
/**
39+
* Insert records from the main index table into the replica table using the given ID
40+
*
41+
* @param string $id
42+
* @return void
43+
*/
44+
public function insertRecords(string $id): void
45+
{
46+
$connection = $this->resourceConnection->getConnection();
47+
$copySelect = $connection->select();
48+
$selectColumns = [
49+
'replica_id' => new \Zend_Db_Expr("'$id'"),
50+
'store_id' => 'store_id',
51+
'product_type' => 'product_type',
52+
'product_id' => 'product_id',
53+
'parent_id' => 'parent_id',
54+
'attribute_data' => 'attribute_data',
55+
56+
];
57+
$copySelect->from(
58+
DataHandler::INDEX_TABLE_NAME,
59+
$selectColumns
60+
);
61+
62+
$copyInsert = $connection->insertFromSelect(
63+
$copySelect,
64+
self::REPLICA_TABLE_NAME
65+
);
66+
$connection->query($copyInsert);
67+
}
68+
69+
/**
70+
* Delete records from the replica table with the given ID
71+
*
72+
* @param string $id
73+
* @return void
74+
*/
75+
public function deleteRecords(string $id): void
76+
{
77+
$connection = $this->resourceConnection->getConnection();
78+
$connection->delete(
79+
self::REPLICA_TABLE_NAME,
80+
['replica_id = ?' => $id]
81+
);
82+
}
83+
}

src/index/Model/Changelog/TempTable.php

Lines changed: 0 additions & 102 deletions
This file was deleted.

0 commit comments

Comments
 (0)