Skip to content

Only resize images (cache) for themes which are being used instead of all installed themes #11514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

denisristic
Copy link
Contributor

Only resize images (cache) for themes which are being used instead of all installed themes

Description

Pull request is using @vrann fix and it is upgraded to check (as suggested in comments) for used (custom) themes in products/categories/cms pages.

Fixed Issues (if relevant)

  1. Extra generated cache images when a product is saved in admin #10363
  2. Catalog image resizing performance problems #8145
  3. Only resize images for themes which are being used instead of all installed themes. #8142

Manual testing scenarios

  1. Add custom theme for product/category/cms page
  2. Disable some theme
  3. Upload product image
  4. Check if cache image is generated for disabled theme

Contribution checklist

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • All automated tests passed successfully (all builds on Travis CI are green)

Denis Ristic added 2 commits October 16, 2017 13:48
…2abcedbe2e67996b043041b48) + added check for used themes in products, categories and cms pages)

REF magento2/issues#10363

UnitTests are failing due to mocking problems:
```
1) Magento\Catalog\Test\Unit\Model\Product\Image\CacheTest::testGenerate
Error: Call to a member function getId() on null
``
@denisristic denisristic changed the title Issue 10363 Only resize images (cache) for themes which are being used instead of all installed themes Oct 17, 2017
@@ -24,11 +27,27 @@ class Cache
protected $themeCollection;

/**
* @var ThemeCustomizationConfig
*/
protected $themeCustomizationConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding new protected properties is expanding the contract of the class, which is not really desired in this case. Please change to private

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to private

*
* @return array
*/
public function getThemesInUse()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this method need to be public?
Please consider extracting it into appropriate service, as getThemesInUse does not seem to have too much in common with Product Image Cache Model.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would you suggest I should put it? Inside themes?

}
}

$connection = $this->attribute->getResource()->getConnection();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting dependencies in such way (one dependency via another one) violates the principle of least knowledge.
Please consider refactoring this.


$productCustomDesignAttributeId = $this->attribute->loadByCode(4, 'custom_design')->getId();

$productSql = $connection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direct access to the data layer is out of responsibilities scope for Magento Models. I suggest to move it into appropriate resource model. This would also help to resolve the commend above (on the least knowledge principle).


$connection = $this->attribute->getResource()->getConnection();

$productCustomDesignAttributeId = $this->attribute->loadByCode(4, 'custom_design')->getId();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to avoid hardcoding the 4?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

*
* @return array
*/
public function getThemesInUse()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add PHP 7.0 specific type hinting and return types to any newly introduced methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

- Adding new protected properties is expanding the contract of the class, which is not really desired in this case. Please change to private
- Please add PHP 7.0 specific type hinting and return types to any newly introduced methods.
- Is there a way to avoid hardcoding the 4?
@ishakhsuvarov ishakhsuvarov self-assigned this Oct 18, 2017
@ishakhsuvarov ishakhsuvarov added this to the October 2017 milestone Oct 18, 2017
@ishakhsuvarov ishakhsuvarov added Release Line: 2.2 2.2.x bug report Component: Catalog improvement Reproduced on 2.1.x The issue has been reproduced on latest 2.1 release Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release labels Oct 18, 2017
@okorshenko okorshenko modified the milestones: October 2017, November 2017 Nov 1, 2017
@ishakhsuvarov ishakhsuvarov removed their assignment Nov 7, 2017
@sidolov sidolov self-assigned this Nov 21, 2017

$productEntityTypeId = \Magento\Catalog\Setup\CategorySetup::CATALOG_PRODUCT_ENTITY_TYPE_ID;

$productCustomDesignAttributeId = $this->attribute->loadByCode($productEntityTypeId, 'custom_design')->getId();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use \Magento\Eav\Model\Config::getAttribute instead of load entity by model


$connection = $this->attribute->getResource()->getConnection();

$productEntityTypeId = \Magento\Catalog\Setup\CategorySetup::CATALOG_PRODUCT_ENTITY_TYPE_ID;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use constant directly instead of assign to variable

@@ -41,11 +60,17 @@ class Cache
public function __construct(
ConfigInterface $viewConfig,
ThemeCollection $themeCollection,
ImageHelper $imageHelper
ImageHelper $imageHelper,
ThemeCustomizationConfig $themeCustomizationConfig,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependencies added with backward compatibility standards violation, right way described in http://devdocs.magento.com/guides/v2.2/contributor-guide/backward-compatible-development/ section: Adding a constructor parameter

$storesByThemes = $this->themeCustomizationConfig->getStoresByThemes();

foreach ($registeredThemes as $registeredTheme) {
if (array_key_exists($registeredTheme->getThemeId(), $storesByThemes)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use $registeredTheme->getCode() instead of $registeredTheme->getThemeId() otherwise this expression will return false permanently and $themesInUse array will be always empty. Without this fix cache directory is empty.

*
* @return array
*/
private function getThemesInUse(): array
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refactoring this logic with introducing composite object (with configuration via DI) for themes in use and move logic to corresponded modules (pages to CMS module; product, category -> Catalog module etc)

/**
* @var Config
*/
protected $eavConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use private modifier for object dependencies

/**
* @var Attribute
*/
protected $attribute;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use private modifier for object dependencies

}
}

$categoryEntityTypeId = \Magento\Catalog\Setup\CategorySetup::CATEGORY_ENTITY_TYPE_ID;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use constant directly instead of assign to variable


$categoryEntityTypeId = \Magento\Catalog\Setup\CategorySetup::CATEGORY_ENTITY_TYPE_ID;

$categoryCustomDesignAttributeId = $this->attribute->loadByCode($categoryEntityTypeId, 'custom_design')->getId();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use \Magento\Eav\Model\Config::getAttribute instead of load entity by model

@sidolov
Copy link
Contributor

sidolov commented Dec 5, 2017

@denisristic, I am closing this PR now due to inactivity.
Please reopen and update if you wish to continue.
Thank you for collaboration

@eharvest
Copy link

Firstly I really want to thank @sidolov for making such effort to offer this solution and I want to give a bit feedback of how it worked for me.

I have a Magento 2.2.3 store (now in production). It has 20k products. Before I run catalog:images:resize the overall size is less than 20G, after run the command a few times (I always delete product image cache before run the command), the size is now growing to nearly 40G. And this what I get:

  • without applying the fix, the command took up to 22 hours to finish and my product image cache grows to 22G!!!
  • after applying the fix, the command took about half the time and my product image cache still as big as 18G. I saved 4G but it's still a lot bigger than I expected. I'm using a child theme, would that be the issue?

I can see there're quite a few developers have been complaining about this, and I really think this is a big performance issue, now we have been forced to use a much bigger server. Hopefully this can be fixed in 2.3 where catalog:images:resize can take args and only apply to the theme in use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report bugfix Component: Catalog improvement Progress: needs update Release Line: 2.2 Reproduced on 2.1.x The issue has been reproduced on latest 2.1 release Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants