Skip to content

Conversation

@oleksii-lisovyi
Copy link

This PR fixes infinite loop issue while using "Save and Duplicate" feature on product edit page in Admin panel.

Description

Removing catching any of \Magento\Framework\Exception\AlreadyExistsException & \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException exceptions prevents getting potential infinite loop, that causes the issues described in the related issue (see below).

Getting infinite loop is caused by issue with incorrect product URL Path re-generation in Catalog URL Rewrite module (here is related PR: #18566).

Fixed Issues (if relevant)

#18532: Module Catalog: product "Save and Duplicate" causes getting infinite loop.

Manual testing scenarios

Perform steps to reproduce from the PR #18566.

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)

…uct "Save and Duplicate" feature in Admin panel
@magento-engcom-team
Copy link
Contributor

Hi @oleksii-lisovyi. Thank you for your contribution
Here is some useful tips how you can test your changes using Magento test environment.
Add the comment under your pull request to deploy test or vanilla Magento instance:

  • @magento-engcom-team give me test instance - deploy test instance based on PR changes
  • @magento-engcom-team give me $VERSION instance - deploy vanilla Magento instance

For more details, please, review the Magento Contributor Assistant documentation

@hostep
Copy link
Contributor

hostep commented Oct 15, 2018

@oleksii-lisovyi, just out of curiosity: did you test it with a product which has a different url_key then the default value on a specific storeview level?
So for example, if the default value for url_key is one, and a storeview specific value is set to two, will this code generate a unique url_key for both the default value (one-1) as the storeview specific value (two-1), or only for the default value?
I have the suspicion that this case might still cause problems, but untested, so I'm not sure.

@hostep
Copy link
Contributor

hostep commented Oct 16, 2018

Just a quick heads up, this commit landed in the 2.3-develop branch yesterday as part of this commit, which might prevent the bug from happening as well, since the url_path gets set to null while duplicating a product. Which might invalidate #18566, but I'm not sure?

But the do while removal in this PR is certainly a good thing!

@orlangur orlangur self-assigned this Oct 17, 2018
? $matches[1] . '-' . ($matches[2] + 1)
: $urlKey . '-1';
$duplicate->setUrlKey($urlKey);
$duplicate->save();
Copy link
Contributor

Choose a reason for hiding this comment

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

Such change is incorrect as new code tries to save duplicate only once - while the whole point of loop was in guaranteed saving of a duplicated product.

@hostep suggestion makes perfect sense to me, please try to do a backport of this logic and check if it solves your problem.

Copy link
Author

@oleksii-lisovyi oleksii-lisovyi Oct 18, 2018

Choose a reason for hiding this comment

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

@orlangur, the only thing, that the loop guarantees, that there will be infinite trials of saving the duplicated product. It doesn't guarantees that the duplicated product actually is saved at the second or third trial and so on.

It means, that having any piece of code, that causes getting any of catched exceptions breaks your website.
It could be not the Magento module, but having such loop makes an opportunity of having infinite loop and broken production, because someone didn't write the module in the right way.

Copy link
Contributor

@hostep hostep Oct 18, 2018

Choose a reason for hiding this comment

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

I agree with @oleksii-lisovyi here, this do while loop can cause major problems, this should be solved in a better way then doing a potential infinite loop.
Finding a unique url key should not be done by trying to save a product over and over again, this should be done separately somehow.

Copy link
Contributor

Choose a reason for hiding this comment

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

@oleksii-lisovyi @hostep

} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
} catch (\Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException $e) {

Such exceptions are specific enough, if some third-party code throws them permanently - it really needs to be fixed.

The problem mentioned is solved in 2.3 and loop is still there:

} while (!$isDuplicateSaved);

Finding a unique url key should not be done by trying to save a product over and over again, this should be done separately somehow.

Please tell more about this "somehow". Main purpose of this code is to avoid race condition (when some URL Key we would use was added by somebody else). Otherwise we would just try the next free URL Key and it would work.

And again, 2.2 should not live on its own, any backportable fix from 2.3 must be backported.

Copy link
Contributor

Choose a reason for hiding this comment

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

Main purpose of this code is to avoid race condition

Aha, I wasn't aware of the purpose of this code, but this makes sense indeed!
Some inline comments might prove useful here.

Please tell more about this "somehow"

If it's to avoid a race condition, then this will be pretty hard to do indeed.
Can't we just show an error when a duplicate url key was detected and tell to user to retry or something like that?

Copy link
Contributor

Choose a reason for hiding this comment

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

@hostep why? This code simply works in 2.3 and I see no issue in it for 2.2

Copy link
Contributor

@hostep hostep Oct 19, 2018

Choose a reason for hiding this comment

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

Because a save method can trigger things you don't want to trigger more than once.
In the case of #9466, calling save more than once copies the image files on the filesystem associated with the product more than once, even though by duplicating a product, you expect the image files to only be copied a single time.

Just some wild idea: can we not first add a completely random unique bunch of characters (a hash if you will) as a url key to the duplicated product, then save the product, and then generate a more sensible url key using that do while loop and only save that on the product so only a single attribute gets changed?

Copy link
Contributor

Choose a reason for hiding this comment

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

@hostep if things are added more than once when calling save, they are not implemented well.

@orlangur
Copy link
Contributor

orlangur commented Nov 7, 2018

@oleksii-lisovyi could you please clarify if #18566 causes #18532 as mentioned in its description or fixes it?

@oleksii-lisovyi
Copy link
Author

@orlangur, looks like the fix I provided fixes the issue with infinite loop.

There is an issue with product images duplicating, that is caused by having this loop: each iteration generates all the images from the original product, but they aren't cleared once duplicated product saving failed.
But, probably fixing that issue is out of scope of this PR. I'm closing the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants