diff --git a/CHANGELOG.md b/CHANGELOG.md
index e118e362a..593ef708e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. This projec
* Update tagging with category listing support
* Add category export
+### 7.2.5
+* Restore `nosto_product_sync.delete` message queue consumer to handle product deletion
+>>>>>>> origin/develop
+
### 7.2.4
* Add null check in order observer to allow for orders overriding
@@ -17,7 +21,7 @@ All notable changes to this project will be documented in this file. This projec
* Add store filter to the DefaulCategoryService to generate categories for specific store
### 7.2.0
-* Remove `nosto_product_sync` message queue consumer
+* Remove `nosto_product_sync.delete` message queue consumer
### 7.1.2
* Remove unreffered system configuration for enabling 'Indexer full reindex' for Nosto indexers
diff --git a/Model/Service/Sync/Delete/AsyncBulkConsumer.php b/Model/Service/Sync/Delete/AsyncBulkConsumer.php
new file mode 100644
index 000000000..0b067ebb5
--- /dev/null
+++ b/Model/Service/Sync/Delete/AsyncBulkConsumer.php
@@ -0,0 +1,93 @@
+
+ * @copyright 2020 Nosto Solutions Ltd
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ *
+ */
+
+namespace Nosto\Tagging\Model\Service\Sync\Delete;
+
+use Nosto\NostoException;
+use Nosto\Tagging\Model\Service\Sync\AbstractBulkConsumer;
+use Nosto\Tagging\Helper\Scope as NostoHelperScope;
+use Magento\Framework\EntityManager\EntityManager;
+use Magento\Framework\Json\Helper\Data as JsonHelper;
+use Nosto\Tagging\Logger\Logger;
+use Magento\Store\Model\App\Emulation;
+
+class AsyncBulkConsumer extends AbstractBulkConsumer
+{
+ /** @var DeleteService */
+ private DeleteService $deleteService;
+
+ /** @var NostoHelperScope */
+ private NostoHelperScope $nostoHelperScope;
+
+ /**
+ * AsyncBulkConsumer constructor.
+ * @param DeleteService $deleteService
+ * @param NostoHelperScope $nostoHelperScope
+ * @param JsonHelper $jsonHelper
+ * @param EntityManager $entityManager
+ * @param Emulation $storeEmulation
+ * @param Logger $logger
+ */
+ public function __construct(
+ DeleteService $deleteService,
+ NostoHelperScope $nostoHelperScope,
+ JsonHelper $jsonHelper,
+ EntityManager $entityManager,
+ Emulation $storeEmulation,
+ Logger $logger
+ ) {
+ $this->deleteService = $deleteService;
+ $this->nostoHelperScope = $nostoHelperScope;
+ parent::__construct(
+ $logger,
+ $jsonHelper,
+ $entityManager,
+ $storeEmulation
+ );
+ }
+
+ /**
+ * @inheritDoc
+ * @param array $productIds
+ * @param string $storeId
+ * @throws NostoException
+ */
+ public function doOperation(array $productIds, string $storeId)
+ {
+ $store = $this->nostoHelperScope->getStore($storeId);
+ $this->deleteService->delete($productIds, $store);
+ }
+}
diff --git a/Model/Service/Sync/Delete/AsyncBulkPublisher.php b/Model/Service/Sync/Delete/AsyncBulkPublisher.php
new file mode 100644
index 000000000..5198406c7
--- /dev/null
+++ b/Model/Service/Sync/Delete/AsyncBulkPublisher.php
@@ -0,0 +1,77 @@
+
+ * @copyright 2020 Nosto Solutions Ltd
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ *
+ */
+
+namespace Nosto\Tagging\Model\Service\Sync\Delete;
+
+use Nosto\Tagging\Model\Service\Sync\AbstractBulkPublisher;
+
+class AsyncBulkPublisher extends AbstractBulkPublisher
+{
+ public const NOSTO_DELETE_MESSAGE_QUEUE = 'nosto_product_sync.delete';
+ public const BULK_SIZE = 100;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTopicName(): string
+ {
+ return self::NOSTO_DELETE_MESSAGE_QUEUE;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBulkSize(): int
+ {
+ return self::BULK_SIZE;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBulkDescription(): string
+ {
+ return sprintf('Delete %d Nosto products', 2);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMetaData(): string
+ {
+ return 'Delete Nosto products';
+ }
+}
diff --git a/Model/Service/Sync/Delete/DeleteService.php b/Model/Service/Sync/Delete/DeleteService.php
new file mode 100644
index 000000000..aafb1f39a
--- /dev/null
+++ b/Model/Service/Sync/Delete/DeleteService.php
@@ -0,0 +1,134 @@
+
+ * @copyright 2020 Nosto Solutions Ltd
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ *
+ */
+
+namespace Nosto\Tagging\Model\Service\Sync\Delete;
+
+use Exception;
+use Magento\Store\Model\Store;
+use Nosto\Model\Signup\Account as NostoSignupAccount;
+use Nosto\NostoException;
+use Nosto\Operation\DeleteProduct;
+use Nosto\Tagging\Helper\Account as NostoHelperAccount;
+use Nosto\Tagging\Helper\Data as NostoHelperData;
+use Nosto\Tagging\Helper\Url as NostoHelperUrl;
+use Nosto\Tagging\Logger\Logger as NostoLogger;
+use Nosto\Tagging\Model\Service\AbstractService;
+use Nosto\Tagging\Model\Service\Cache\CacheService;
+
+class DeleteService extends AbstractService
+{
+
+ public const BENCHMARK_DELETE_NAME = 'nosto_product_delete';
+ public const BENCHMARK_DELETE_BREAKPOINT = 1;
+ public const PRODUCT_DELETION_BATCH_SIZE = 100;
+
+ /** @var CacheService */
+ private CacheService $cacheService;
+
+ /** @var NostoHelperAccount */
+ private NostoHelperAccount $nostoHelperAccount;
+
+ /** @var NostoHelperUrl */
+ private NostoHelperUrl $nostoHelperUrl;
+
+ /** @var int */
+ private int $deleteBatchSize;
+
+ /**
+ * DeleteService constructor.
+ * @param CacheService $cacheService
+ * @param NostoHelperAccount $nostoHelperAccount
+ * @param NostoHelperData $nostoHelperData
+ * @param NostoHelperUrl $nostoHelperUrl
+ * @param NostoLogger $logger
+ * @param $deleteBatchSize
+ */
+ public function __construct(
+ CacheService $cacheService,
+ NostoHelperAccount $nostoHelperAccount,
+ NostoHelperData $nostoHelperData,
+ NostoHelperUrl $nostoHelperUrl,
+ NostoLogger $logger,
+ $deleteBatchSize
+ ) {
+ $this->cacheService = $cacheService;
+ $this->nostoHelperAccount = $nostoHelperAccount;
+ $this->nostoHelperUrl = $nostoHelperUrl;
+ $this->deleteBatchSize = $deleteBatchSize;
+ parent::__construct($nostoHelperData, $nostoHelperAccount, $logger);
+ }
+
+ /**
+ * Discontinues products in Nosto and removes indexed products from Nosto product index
+ *
+ * @param array $productIds
+ * @param Store $store
+ * @throws NostoException
+ */
+ public function delete(array $productIds, Store $store)
+ {
+ if (count($productIds) === 0) {
+ return;
+ }
+ $account = $this->nostoHelperAccount->findAccount($store);
+ if ($account instanceof NostoSignupAccount === false) {
+ throw new NostoException(sprintf('Store view %s does not have Nosto installed', $store->getName()));
+ }
+ $this->startBenchmark(self::BENCHMARK_DELETE_NAME, self::BENCHMARK_DELETE_BREAKPOINT);
+ $productIdBatches = array_chunk($productIds, $this->deleteBatchSize);
+ $this->logDebugWithStore(
+ sprintf(
+ 'Deleting total of %d products in batches of %d',
+ count($productIds),
+ count($productIdBatches)
+ ),
+ $store
+ );
+ foreach ($productIdBatches as $ids) {
+ try {
+ $op = new DeleteProduct($account, $this->nostoHelperUrl->getActiveDomain($store));
+ $op->setResponseTimeout(30);
+ $op->setProductIds($ids);
+ $op->delete(); // @codingStandardsIgnoreLine
+ $this->cacheService->removeByProductIds($store, $ids);
+ $this->tickBenchmark(self::BENCHMARK_DELETE_NAME);
+ } catch (Exception $e) {
+ $this->getLogger()->exception($e);
+ }
+ }
+ $this->logBenchmarkSummary(self::BENCHMARK_DELETE_NAME, $store);
+ }
+}
diff --git a/Model/Service/Update/ProductUpdateService.php b/Model/Service/Update/ProductUpdateService.php
index 12c6a6946..665d286fa 100644
--- a/Model/Service/Update/ProductUpdateService.php
+++ b/Model/Service/Update/ProductUpdateService.php
@@ -61,6 +61,9 @@ class ProductUpdateService extends AbstractService
/** @var BulkPublisherInterface */
private BulkPublisherInterface $upsertBulkPublisher;
+ /** @var BulkPublisherInterface */
+ private BulkPublisherInterface $deleteBulkPublisher;
+
/**
* ProductUpdateService constructor.
* @param NostoLogger $logger
@@ -68,6 +71,7 @@ class ProductUpdateService extends AbstractService
* @param NostoAccountHelper $nostoAccountHelper
* @param NostoProductRepository $nostoProductRepository
* @param BulkPublisherInterface $upsertBulkPublisher
+ * @param BulkPublisherInterface $deleteBulkPublisher
* @param int $batchSize
*/
public function __construct(
@@ -76,11 +80,13 @@ public function __construct(
NostoAccountHelper $nostoAccountHelper,
NostoProductRepository $nostoProductRepository,
BulkPublisherInterface $upsertBulkPublisher,
+ BulkPublisherInterface $deleteBulkPublisher,
int $batchSize
) {
parent::__construct($nostoDataHelper, $nostoAccountHelper, $logger);
$this->nostoProductRepository = $nostoProductRepository;
$this->upsertBulkPublisher = $upsertBulkPublisher;
+ $this->deleteBulkPublisher = $deleteBulkPublisher;
$this->batchSize = $batchSize;
}
@@ -117,6 +123,24 @@ public function addCollectionToUpdateMessageQueue(ProductCollection $collection,
}
}
+ /**
+ * Sets the product ids into the delete message queue
+ *
+ * @param array $productIds
+ * @param Store $store
+ */
+ public function addIdsToDeleteMessageQueue(array $productIds, Store $store)
+ {
+ if ($this->getAccountHelper()->findAccount($store) === null) {
+ $this->logDebugWithStore('No nosto account found for the store', $store);
+ return;
+ }
+ $batchedIds = array_chunk($productIds, $this->batchSize);
+ foreach ($batchedIds as $idBatch) {
+ $this->deleteBulkPublisher->execute($store->getId(), $idBatch);
+ }
+ }
+
/**
* @param ProductCollection $collection
* @return array
diff --git a/Plugin/ProductUpdate.php b/Plugin/ProductUpdate.php
index 895582654..c81d23792 100644
--- a/Plugin/ProductUpdate.php
+++ b/Plugin/ProductUpdate.php
@@ -41,9 +41,12 @@
use Magento\Framework\Indexer\IndexerRegistry;
use Magento\Framework\Model\AbstractModel;
use Nosto\Tagging\Exception\ParentProductDisabledException;
+use Nosto\Tagging\Helper\Scope as NostoHelperScope;
use Nosto\Tagging\Model\Indexer\ProductIndexer;
use Nosto\Tagging\Model\Product\Repository as NostoProductRepository;
use Nosto\Tagging\Logger\Logger as NostoLogger;
+use Nosto\Tagging\Model\ResourceModel\Magento\Product\CollectionBuilder;
+use Nosto\Tagging\Model\Service\Update\ProductUpdateService;
/**
* Plugin for product updates
@@ -62,23 +65,40 @@ class ProductUpdate
/** @var NostoLogger */
private NostoLogger $logger;
+ /** @var ProductUpdateService */
+ private ProductUpdateService $productUpdateService;
+
+ /** @var NostoHelperScope */
+ private NostoHelperScope $nostoHelperScope;
+
+ /** @var CollectionBuilder */
+ private CollectionBuilder $productCollectionBuilder;
+
/**
* ProductUpdate constructor.
* @param IndexerRegistry $indexerRegistry
* @param ProductIndexer $productIndexer
* @param NostoProductRepository $nostoProductRepository
* @param NostoLogger $logger
+ * @param ProductUpdateService $productUpdateService
+ * @param NostoHelperScope $nostoHelperScope
*/
public function __construct(
- IndexerRegistry $indexerRegistry,
- ProductIndexer $productIndexer,
- NostoProductRepository $nostoProductRepository,
- NostoLogger $logger
+ IndexerRegistry $indexerRegistry,
+ ProductIndexer $productIndexer,
+ NostoProductRepository $nostoProductRepository,
+ NostoLogger $logger,
+ ProductUpdateService $productUpdateService,
+ NostoHelperScope $nostoHelperScope,
+ CollectionBuilder $productCollectionBuilder
) {
$this->indexerRegistry = $indexerRegistry;
$this->productIndexer = $productIndexer;
$this->nostoProductRepository = $nostoProductRepository;
$this->logger = $logger;
+ $this->productUpdateService = $productUpdateService;
+ $this->nostoHelperScope = $nostoHelperScope;
+ $this->productCollectionBuilder = $productCollectionBuilder;
}
/**
@@ -115,26 +135,35 @@ public function aroundDelete(
Closure $proceed,
AbstractModel $product
) {
- $mageIndexer = $this->indexerRegistry->get(ProductIndexer::INDEXER_ID);
- if (!$mageIndexer->isScheduled()) {
+ try {
+ $productIds = $this->nostoProductRepository->resolveParentProductIds($product);
+ } catch (ParentProductDisabledException $e) {
+ $this->logger->debug($e->getMessage());
+ return $proceed($product);
+ }
- try {
- $productIds = $this->nostoProductRepository->resolveParentProductIds($product);
- } catch (ParentProductDisabledException $e) {
- $this->logger->debug($e->getMessage());
- return $proceed($product);
- }
-
- if (empty($productIds)) {
- $productResource->addCommitCallback(function () use ($product) {
- $this->productIndexer->executeRow($product->getId());
- });
- }
- if (is_array($productIds) && !empty($productIds)) {
- $productResource->addCommitCallback(function () use ($productIds) {
- $this->productIndexer->executeList($productIds);
- });
- }
+ $storeIds = $product->getStoreIds();
+
+ // The current product does not have parent product
+ if (empty($productIds)) {
+ $productResource->addCommitCallback(function () use ($product, $storeIds) {
+ foreach ($storeIds as $storeId) {
+ $store = $this->nostoHelperScope->getStore($storeId);
+ $this->productUpdateService->addIdsToDeleteMessageQueue([$product->getId()], $store);
+ }
+ });
+ }
+
+ // Current product is child product
+ if (is_array($productIds) && !empty($productIds)) {
+ $productResource->addCommitCallback(function () use ($productIds, $storeIds) {
+ $productCollection = $this->productCollectionBuilder->withIds($productIds)->build();
+
+ foreach ($storeIds as $storeId) {
+ $store = $this->nostoHelperScope->getStore($storeId);
+ $this->productUpdateService->addCollectionToUpdateMessageQueue($productCollection, $store);
+ }
+ });
}
return $proceed($product);
diff --git a/composer.json b/composer.json
index e50d21d1f..7673e00c9 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "nosto/module-nostotagging",
"description": "Increase your conversion rate and average order value by delivering your customers personalized product recommendations throughout their shopping journey.",
"type": "magento2-module",
- "version": "7.2.4",
+ "version": "7.2.5",
"require-dev": {
"phpmd/phpmd": "^2.5",
"sebastian/phpcpd": "*",
@@ -41,7 +41,7 @@
"php": ">=7.4.0",
"magento/framework": ">=101.0.6|~104.0",
"ext-json": "*",
- "nosto/php-sdk": "dev-hotfix/fix-update-category"
+ "nosto/php-sdk": "^7.1"
},
"repositories": [
{
diff --git a/composer.lock b/composer.lock
index c08646609..ab769840f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "5d5b24449493c6a2fc300fae27501844",
+ "content-hash": "aa6d7af5994cf533b8e395bf62d5c06d",
"packages": [
{
"name": "brick/math",
@@ -2866,16 +2866,16 @@
},
{
"name": "nosto/php-sdk",
- "version": "dev-hotfix/fix-update-category",
+ "version": "7.1.1",
"source": {
"type": "git",
"url": "https://github.com/Nosto/nosto-php-sdk.git",
- "reference": "9a479e74ddd84df77b590d0818e008f99218d1bc"
+ "reference": "8f14a91acf7f60f6fb48eab1dfdd61a7f97eef4f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Nosto/nosto-php-sdk/zipball/9a479e74ddd84df77b590d0818e008f99218d1bc",
- "reference": "9a479e74ddd84df77b590d0818e008f99218d1bc",
+ "url": "https://api.github.com/repos/Nosto/nosto-php-sdk/zipball/8f14a91acf7f60f6fb48eab1dfdd61a7f97eef4f",
+ "reference": "8f14a91acf7f60f6fb48eab1dfdd61a7f97eef4f",
"shasum": ""
},
"require": {
@@ -2916,9 +2916,9 @@
"description": "PHP SDK for developing Nosto modules for e-commerce platforms",
"support": {
"issues": "https://github.com/Nosto/nosto-php-sdk/issues",
- "source": "https://github.com/Nosto/nosto-php-sdk/tree/hotfix/fix-update-category"
+ "source": "https://github.com/Nosto/nosto-php-sdk/tree/7.1.1"
},
- "time": "2023-06-15T08:38:35+00:00"
+ "time": "2023-06-27T11:31:54+00:00"
},
{
"name": "paragonie/constant_time_encoding",
@@ -12255,9 +12255,7 @@
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": {
- "nosto/php-sdk": 20
- },
+ "stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
diff --git a/etc/communication.xml b/etc/communication.xml
index 677b07327..bbbd74187 100644
--- a/etc/communication.xml
+++ b/etc/communication.xml
@@ -38,4 +38,7 @@