Smile-SA / elasticsuite

Smile ElasticSuite - Magento 2 merchandising and search engine built on ElasticSearch
https://elasticsuite.io
Open Software License 3.0
761 stars 341 forks source link

Can not install Elasticsuite 2.7.0 #1222

Closed minhluan259 closed 5 years ago

minhluan259 commented 5 years ago

Cannot instantiate interface Magento\InventorySalesApi\Api\StockResolverInterface

Preconditions

PHP 7.1.24, Elasticsearch 6.5

Magento Version : 2.3.0 CE

ElasticSuite Version : 2.7.0

Environment : Production

Third party modules : none

Steps to reproduce

After require and add config Elasticsuite follow wiki document run command bin/magento setup:upgrade

Expected result

  1. Install Elasticsuite without error

Actual result

  1. [Screenshot, logs]
    Module 'Magento_WishlistAnalytics':
    Module 'Smile_ElasticsuiteCore':
    Module 'Smile_ElasticsuiteCatalog':
    Installing data... PHP Fatal error:  Uncaught Error: Cannot instantiate interface Magento\InventorySalesApi\Api\StockResolverInterface in /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php:50
    Stack trace:
    #0 /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/ObjectManager.php(70): Magento\Framework\ObjectManager\Factory\Dynamic\Developer->create('Magento\\Invento...')
    #1 /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(160): Magento\Framework\ObjectManager\ObjectManager->get('Magento\\Invento...')
    #2 /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(246): Magento\Framework\ObjectManager\Factory\AbstractFactory->resolveArgument(Array, 'Magento\\Invento...', NULL, 'stockResolver', 'Smile\\Elasticsu...')
    #3 /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php(34): Magento\Framework\ObjectManager\Factory\AbstractFactory->resol in /var/www/clients/client0/web6/web/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php on line 50
Swahjak commented 5 years ago

This seems to be related to your installation. Magento\InventorySalesApi\Api\StockResolverInterface should be available in vendor/magento/module-inventory-sales-api/Api/StockResolverInterface.php on a Magento 2.3 installation (and mapped in vendor/magento/module-inventory-sales/etc/di.xml to <preference for="Magento\InventorySalesApi\Api\StockResolverInterface" type="Magento\InventorySales\Model\StockResolver"/>.

We've had the same 'issue' but it was due to the fact that we had removed the magento/module-inventory-sales-api using composer replace. Could also be related to the generated folder or old cache.

rbayet commented 5 years ago

Re-opening the issue as in the course of the dev, an additional module was created with correct extra dependencies. Those extra dependencies were not reported to Smile_ElasticsuiteCatalog when the additional module was dropped.

rbayet commented 5 years ago

Fixed by PR #1229 in release 2.7.1

Yamaha32088 commented 5 years ago

@rbayet I am having the same problem even after installing the 2.7.1 version of ElasticSuite.

[Fri Dec 14 22:27:37.192325 2018] [php7:error] [pid 3431] [client xxxxxxx:58508] PHP Fatal error:  Uncaught Error: Cannot instantiate interface Magento\\InventorySalesApi\\Api\\StockResolverInterface in /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php:116\nStack trace:\n#0 /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/Compiled.php(108): Magento\\Framework\\ObjectManager\\Factory\\AbstractFactory->createObject('Magento\\\\Invento...', Array)\n#1 /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/Compiled.php(150): Magento\\Framework\\ObjectManager\\Factory\\Compiled->create('Magento\\\\Invento...')\n#2 /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/Compiled.php(79): Magento\\Framework\\ObjectManager\\Factory\\Compiled->get('Magento\\\\Invento...')\n#3 /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/Compiled.php(150): Magento\\Framework\\ObjectManager\\Factory\\Compiled->create('Smile\\\\Elasticsu...')\n#4 /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/Compiled.php(79): Magento\\Framework\\ObjectManager\\Factory\\Compiled->get('Sm in /var/www/devsite/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 116
Swahjak commented 5 years ago

https://github.com/Smile-SA/elasticsuite/blob/2.7.1/composer.json#L33

Are you running with MAGE_MODE=production? Because you are running through vendor/magento/framework/ObjectManager/Factory/Compiled.php(108) which would suggest you have compiled Magento using bin/magento setup:compile.

Yamaha32088 commented 5 years ago

@Swahjak yes it is running in production mode and I do run bin/magento setup:compile

husseycoding commented 5 years ago

Seeing this issue with Magento 2.3 and module version 2.7.2. Worth noting that this is actually an issue with reindexing, it shows during installation as data setup runs a reindex.

andykim commented 5 years ago

I upgrade to Magento 2.3 and install elasticsuite v2.7.2 and when i run php bin/magento setup:upgrade

Module 'Smile_ElasticsuiteCore':
Module 'Smile_ElasticsuiteCatalog':
Installing data... PHP Fatal error:  Uncaught Error: Cannot instantiate interface Magento\InventorySalesApi\Api\StockResolverInterface in /hdd/www/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php:50
Stack trace:
#0 /hdd/www/vendor/magento/framework/ObjectManager/ObjectManager.php(70): Magento\Framework\ObjectManager\Factory\Dynamic\Developer->create('Magento\\Invento...')
#1 /hdd/www/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(160): Magento\Framework\ObjectManager\ObjectManager->get('Magento\\Invento...')
#2 /hdd/www/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(246): Magento\Framework\ObjectManager\Factory\AbstractFactory->resolveArgument(Array, 'Magento\\Invento...', NULL, 'stockResolver', 'Smile\\Elasticsu...')
#3 /hdd/www/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php(34): Magento\Framework\ObjectManager\Factory\AbstractFactory->resolveArgumentsInRu in /hdd/www/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php on line 50
VincentJorge commented 5 years ago

Hello Guys,

Anyone have a news about this issue ?

Thank's

hectorrojas4 commented 5 years ago

If the class Magento\InventorySalesApi\Api\StockResolverInterface cannot be instantiated, it is possible that the module is disabled in app/etc/config.php file. Make sure that the Inventory modules are enabled:

<?php
return [
    'modules' => [
        ...
        'Magento_Inventory' => 1,
        'Magento_InventoryAdminUi' => 1,
        'Magento_InventoryApi' => 1,
        'Magento_InventoryBundleProduct' => 1,
        'Magento_InventoryBundleProductAdminUi' => 1,
        'Magento_InventoryCatalog' => 1,
        'Magento_InventorySales' => 1,
        'Magento_InventoryCatalogAdminUi' => 1,
        'Magento_InventoryCatalogApi' => 1,
        'Magento_InventoryCatalogSearch' => 1,
        'Magento_InventoryConfigurableProduct' => 1,
        'Magento_InventoryConfigurableProductAdminUi' => 1,
        'Magento_InventoryConfigurableProductIndexer' => 1,
        'Magento_InventoryConfiguration' => 1,
        'Magento_InventoryConfigurationApi' => 1,
        'Magento_InventoryGroupedProduct' => 1,
        'Magento_InventoryGroupedProductAdminUi' => 1,
        'Magento_InventoryGroupedProductIndexer' => 1,
        'Magento_InventoryImportExport' => 1,
        'Magento_InventoryIndexer' => 1,
        'Magento_InventoryLowQuantityNotification' => 1,
        'Magento_InventoryLowQuantityNotificationAdminUi' => 1,
        'Magento_InventoryLowQuantityNotificationApi' => 1,
        'Magento_InventoryMultiDimensionalIndexerApi' => 1,
        'Magento_InventoryProductAlert' => 1,
        'Magento_InventoryReservations' => 1,
        'Magento_InventoryReservationsApi' => 1,
        'Magento_InventoryCache' => 1,
        'Magento_InventorySalesAdminUi' => 1,
        'Magento_InventorySalesApi' => 1,
        'Magento_InventorySalesFrontendUi' => 1,
        'Magento_InventoryShipping' => 1,
        'Magento_InventorySourceDeductionApi' => 1,
        'Magento_InventorySourceSelection' => 1,
        'Magento_InventorySourceSelectionApi' => 1,
        ...
    ]
];
minhluan259 commented 5 years ago

I found the cause of the problem because upgraded magento 2.2 to magento 2.3 incorrectly. Follow this guide https://devdocs.magento.com/guides/v2.3/comp-mgr/cli/cli-upgrade.html to resolved the issue. Hope this can help.

frostblogNet commented 5 years ago

Hello @minhluan259

I have followed this guide but I ran into the same problem. Can you tell me want exactly was the solution.

Thanks in advance Jens

EDIT:

Solution:

php bin/magento module:enable Magento_Inventory Magento_InventoryApi Magento_InventoryCatalogApi Magento_InventorySalesApi Magento_InventoryConfigurationApi Magento_InventoryReservationsApi Magento_InventorySourceDeductionApi Magento_SalesInventory Magento_InventorySales Magento_InventoryMultiDimensionalIndexerApi Magento_InventoryIndexer Magento_InventoryConfiguration Magento_InventoryCatalog Magento_InventoryReservations Magento_InventoryReservationsApi

Then you should be able to run setup:upgrade

Als described here https://github.com/Smile-SA/elasticsuite/issues/1243 by @joshmcoffman

paalsoberg commented 5 years ago

What about if you don't want the inventory / MSI modules installed?

Swahjak commented 5 years ago

@paalsoberg There has been some discussion about that in https://github.com/Smile-SA/elasticsuite/issues/1517

rbayet commented 5 years ago

Hello @paalsoberg,

2.7.7 and 2.8.0 releases introduced a fix that should allow you to use either the MSI modules or the legacy cataloginventory module. Unless you're using PHP 7.3 which does not like a particular return type annotation : this is to be addressed in our (very soon) incoming 2.8.3 release.

Regards,

Swahjak commented 5 years ago

@rbayet Will this still require installation (with composer) of the msi modules?

rbayet commented 5 years ago

@Swahjak Yes, the MSI modules magento/module-inventory-sales-api, magento/module-inventory-sales and magento/module-inventory-indexer are still present in our composer.json so those will be required at install.

They are also present in smile/module-elasticsuite-catalog's module.xml file but you can disable them. Well them and the modules they are required for or simply ALL the MSI modules in one go with (on a CE 2.3.3) : php bin/magento module:disable Magento_Inventory Magento_InventoryAdminUi Magento_InventoryAdvancedCheckout Magento_InventoryApi Magento_InventoryBundleProduct Magento_InventoryBundleProductAdminUi Magento_InventoryCatalog Magento_InventorySales Magento_InventoryCatalogAdminUi Magento_InventoryCatalogApi Magento_InventoryCatalogSearch Magento_InventoryConfigurableProduct Magento_InventoryConfigurableProductAdminUi Magento_InventoryConfigurableProductIndexer Magento_InventoryConfiguration Magento_InventoryConfigurationApi Magento_InventoryDistanceBasedSourceSelection Magento_InventoryDistanceBasedSourceSelectionAdminUi Magento_InventoryDistanceBasedSourceSelectionApi Magento_InventoryElasticsearch Magento_InventoryExportStockApi Magento_InventoryIndexer Magento_InventorySalesApi Magento_InventoryGroupedProduct Magento_InventoryGroupedProductAdminUi Magento_InventoryGroupedProductIndexer Magento_InventoryImportExport Magento_InventoryCache Magento_InventoryLowQuantityNotification Magento_InventoryLowQuantityNotificationAdminUi Magento_InventoryLowQuantityNotificationApi Magento_InventoryMultiDimensionalIndexerApi Magento_InventoryProductAlert Magento_InventoryRequisitionList Magento_InventoryReservations Magento_InventoryReservationCli Magento_InventoryReservationsApi Magento_InventoryExportStock Magento_InventorySalesAdminUi Magento_InventorySalesFrontendUi Magento_InventorySetupFixtureGenerator Magento_InventoryShipping Magento_InventorySourceDeductionApi Magento_InventorySourceSelection Magento_InventorySourceSelectionApi Magento_InventoryShippingAdminUi Magento_InventoryGraphQl and have your instance still working correctly.

The same way Magento_LayeredNavigationStaging is referenced in smile/module-elasticsuite-catalog module.xml without issue on CE/Open Source versions of M2 where this module simply does not exist.

Regards

SolsWebdesign commented 5 years ago

We really have no need for MultiStock and to keep the shop lean and fast we have disabled (and completely removed) MultiStock and we are running into compilation errors: [ReflectionException] Class Magento\InventorySalesApi\Api\StockResolverInterface does not exist It would really be nice if this can be changed so removing the modules will not cause these errors.

Sorry, I did not mean to confuse anybody. Thanks to @rbayet s comment I understood that it is crucial to have MSI installed (albeit disabled) so it works fine... But we would rather have a smaller code base since this shop is quite heavy. And only installing the three needed modules (module-inventory-sales-api, module-inventory-sales and module-inventory-indexer) was not enough: di:compile seems to require all of them. Elasticsuite works fine, I just need to see about the MSI.

romainruaud commented 5 years ago

@SolsWebdesign please don't publish messages in closed issues but open a new one instead if you have issue.

That being said, you should not "remove completely" MSI. You just have to disable all Magento_InventoryXXX modules but keep them installed.

And of course, you have to use at least ElasticSuite >2.7.7.

Regards

rbayet commented 5 years ago

@SolsWebdesign for the sake of clarity, please open a specific issue, stating the versions of M2 and Elasticsuite you are using, considering, as shown in my previous comment above and the following, there should not be any problem remaining. It that is still the case, we'll investigate.

Regards,

peterjaap commented 3 years ago

@SolsWebdesign @paalsoberg

Here's a patch I made to make Elasticsuite work without any MSI modules actually installed (so removed with the composer replace trick). Formatted for use with vaimo/composer-patches.

Removed dependency on MSI modules

@package smile/elasticsuite
@link https://github.com/Smile-SA/elasticsuite/issues/1222

diff --git src/module-elasticsuite-catalog/Model/Product/Indexer/Fulltext/Datasource/InventoryData.php src/module-elasticsuite-catalog/Model/Product/Indexer/Fulltext/Datasource/InventoryData.php
index ca4557d..f07e059 100644
--- src/module-elasticsuite-catalog/Model/Product/Indexer/Fulltext/Datasource/InventoryData.php
+++ src/module-elasticsuite-catalog/Model/Product/Indexer/Fulltext/Datasource/InventoryData.php
@@ -14,7 +14,6 @@
 namespace Smile\ElasticsuiteCatalog\Model\Product\Indexer\Fulltext\Datasource;

 use Smile\ElasticsuiteCore\Api\Index\DatasourceInterface;
-use Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\InventoryDataInterface;
 use \Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\Deprecation\InventoryData as Deprecation;

 /**
@@ -27,7 +26,7 @@ use \Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Data
 class InventoryData implements DatasourceInterface
 {
     /**
-     * @var InventoryDataInterface
+     * @var Deprecation
      */
     private $resourceModel;

@@ -75,31 +74,15 @@ class InventoryData implements DatasourceInterface
     }

     /**
-     * Init proper resource model.
-     *
-     * Should be default implementation of InventoryDataInterface if MSI modules are enabled.
-     *
-     * Otherwise we fallback to old-style CatalogInventory indexing.
      *
      * @deprecated To be removed with Magento 2.4 and the dismantlement of legacy CatalogInventory module.
      *
-     * @return InventoryDataInterface
+     * @return Deprecation
      */
     private function getResourceModel()
     {
         if ($this->resourceModel === null) {
-            $resourceName = InventoryDataInterface::class;
-
-            try {
-                // Will try to fetch default implementation and fail in case of missing MSI modules or dependencies.
-                $stockResolver = $this->config->getPreference(\Magento\InventorySalesApi\Api\StockResolverInterface::class);
-                if (ltrim($stockResolver, '\\') === ltrim(\Magento\InventorySalesApi\Api\StockResolverInterface::class, '\\')) {
-                    $resourceName = Deprecation::class;
-                }
-            } catch (\Exception $exception) {
-                ; // Nothing to do, it's already kinda hacky to allow this deprecation fallback to happen.
-            }
-
+            $resourceName = Deprecation::class;
             $this->resourceModel = $this->objectManager->get($resourceName);
         }

diff --git src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/InventoryData.php src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/InventoryData.php
deleted file mode 100644
index 5ee7d1e..0000000
--- src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/InventoryData.php
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-/**
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
- * versions in the future.
- *
- * @category  Smile
- * @package   Smile\ElasticsuiteCatalog
- * @author    Romain Ruaud <romain.ruaud@smile.fr>
- * @copyright 2020 Smile
- * @license   Open Software License ("OSL") v. 3.0
- */
-namespace Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource;
-
-use Smile\ElasticsuiteCatalog\Model\ResourceModel\Eav\Indexer\Indexer;
-use Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\InventoryDataInterface;
-use Magento\Framework\App\ResourceConnection;
-use Magento\Framework\EntityManager\MetadataPool;
-use Magento\Store\Model\StoreManagerInterface;
-use Magento\InventorySalesApi\Api\Data\SalesChannelInterface;
-use Magento\InventorySalesApi\Api\StockResolverInterface;
-use Magento\InventoryIndexer\Model\StockIndexTableNameResolverInterface;
-use Magento\InventoryIndexer\Indexer\IndexStructure;
-
-/**
- * Multi Source Inventory Catalog Inventory Data source resource model
- *
- * @category Smile
- * @package  Smile\ElasticsuiteCatalog
- * @author   Romain Ruaud <romain.ruaud@smile.fr>
- */
-class InventoryData extends Indexer implements InventoryDataInterface
-{
-    /**
-     * @var StockResolverInterface
-     */
-    private $stockResolver;
-
-    /**
-     * @var StockIndexTableNameResolverInterface
-     */
-    private $stockIndexTableProvider;
-
-    /**
-     * @var int[]
-     */
-    private $stockIdByWebsite = [];
-
-    /**
-     * InventoryData constructor.
-     *
-     * @param ResourceConnection                   $resource                Database adapter.
-     * @param StoreManagerInterface                $storeManager            Store manager.
-     * @param MetadataPool                         $metadataPool            Metadata Pool
-     * @param StockResolverInterface               $stockResolver           Stock resolver.
-     * @param StockIndexTableNameResolverInterface $stockIndexTableProvider Stock index table provider.
-     */
-    public function __construct(
-        ResourceConnection $resource,
-        StoreManagerInterface $storeManager,
-        MetadataPool $metadataPool,
-        StockResolverInterface $stockResolver,
-        StockIndexTableNameResolverInterface $stockIndexTableProvider
-    ) {
-        $this->stockResolver = $stockResolver;
-        $this->stockIndexTableProvider = $stockIndexTableProvider;
-
-        parent::__construct($resource, $storeManager, $metadataPool);
-    }
-
-    /**
-     * Load inventory data for a list of product ids and a given store.
-     * Expected rows structure : ['product_id', 'stock_status', 'qty'].
-     *
-     * @param integer $storeId    Store id.
-     * @param array   $productIds Product ids list.
-     *
-     * @return array
-     */
-    public function loadInventoryData($storeId, $productIds)
-    {
-        $websiteId = $this->getWebsiteId($storeId);
-        $stockId   = $this->getStockId($websiteId);
-        $tableName = $this->stockIndexTableProvider->execute($stockId);
-
-        $select = $this->getConnection()->select()
-            ->from(['product' => $this->getTable('catalog_product_entity')], [])
-            ->join(
-                ['stock_index' => $tableName],
-                'product.sku = stock_index.' . IndexStructure::SKU,
-                [
-                    'product_id'    => 'product.entity_id',
-                    'stock_status'  => 'stock_index.' . IndexStructure::IS_SALABLE,
-                    'qty'           => 'stock_index.' . IndexStructure::QUANTITY,
-                ]
-            )
-            ->where('product.entity_id IN (?)', $productIds)
-            ->group('product.entity_id');
-
-        return $this->getConnection()->fetchAll($select);
-    }
-
-    /**
-     * Retrieve stock_id by website
-     *
-     * @param int $websiteId The website Id
-     *
-     * @return int
-     */
-    private function getStockId($websiteId)
-    {
-        if (!isset($this->stockIdByWebsite[$websiteId])) {
-            $websiteCode = $this->storeManager->getWebsite($websiteId)->getCode();
-            $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode);
-            $stockId = (int) $stock->getStockId();
-            $this->stockIdByWebsite[$websiteId] = $stockId;
-        }
-
-        return $this->stockIdByWebsite[$websiteId];
-    }
-
-    /**
-     * Retrieve Website Id by Store Id
-     *
-     * @param int $storeId The store id
-     *
-     * @return int
-     */
-    private function getWebsiteId($storeId)
-    {
-        return $this->storeManager->getStore($storeId)->getWebsiteId();
-    }
-}
diff --git src/module-elasticsuite-catalog/etc/di.xml src/module-elasticsuite-catalog/etc/di.xml
index 8121b1d..67d6ff0 100644
--- src/module-elasticsuite-catalog/etc/di.xml
+++ src/module-elasticsuite-catalog/etc/di.xml
@@ -275,9 +275,6 @@
         </arguments>
     </type>

-    <preference for="Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\InventoryDataInterface"
-                type="Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\InventoryData" />
-
     <virtualType name="Smile\ElasticsuiteCatalog\Search\Request\Product\Coverage\Builder"
         type="\Smile\ElasticsuiteCore\Search\Request\Builder">
         <arguments>