Closed vbuck closed 3 years ago
Hi @vbuck. Thank you for your report. To help us process this issue please make sure that you provided the following information:
Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:
@magento give me 2.4-develop instance
- upcoming 2.4.x release
For more details, please, review the Magento Contributor Assistant documentation.
@vbuck do you confirm that you were able to reproduce the issue on vanilla Magento instance following steps to reproduce?
Following up on this to request attention.
Also, I checked "no" incorrectly to the reproduction steps. I was able to reproduce it on a vanilla 2.3 instance.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 14 days if no further activity occurs. Is this issue still relevant? If so, what is blocking it? Is there anything you can do to help move it forward? Thank you for your contributions!
When any integration uses the Magento rule system (even core sales rules), products may be loaded unnecessarily during rule validation.
Reference:
\Magento\Rule\Model\Condition\AbstractCondition::validate
Preconditions (*)
Steps to reproduce (*)
test_attribute
, type text, values required: no\Magento\Rule\Model\Condition\AbstractCondition::validate
test_attribute
key on product objectThis illustrates the problem. To prove it another way:
\Magento\Rule\Model\Condition\AbstractCondition::validate
Expected result (*)
Actual result (*)
Additional Information
I discovered this issue in a vendor integration (Amasty Shipping Restrictions) when reviewing performance profiles. Curiously, Magento 1 does not behave this way (see
\Mage_Rule_Model_Condition_Abstract::validate
). I'm not a historian but given the refactor for M2, I'd suggest the developer was either actively solving for a known issue or else attempted a QoL improvement when translating the code.I don't personally believe that rule validation should have any part in loading models. The requestor should be responsible for supplying all needed information to the validator. And if it isn't present, it should be treated as "not available," but not attempt to go load the value. I would even take that so far as to say the
validate
method should expect a more genericDataObject
or plain DTO as a way to more strictly enforce this idea.As an extra technical detail, the root cause for this situation is the attribute persister mechanism:
\Magento\Eav\Model\ResourceModel\UpdateHandler::execute
This acts as a self-cleaning mechanism to delete EAV rows that hold "empty-ish" values when saving products. While I agree with this approach, it requires the developer to be aware of its effects (which previously I was not!). For example, I would expect that every attribute assigned to a set has a property initialized (even if empty) on product models that are members of the attribute set. Therefore,DataObject::hasData
should always return true for my attribute check; ieDataObject::hasData('test_attribute')
. Or else, we redefine the meaning of "has data" (but that's another story).My point is, the logic in
\Magento\Rule\Model\Condition\AbstractCondition::validate
seems misguided. I believe that a blind check for the value of the attribute here is sufficient. We don't need to know whether the property has been initialized. Let the mixed return type ofgetData
and loose type comparison suffice for completing validation. That would be in agreement with the broad usability of the abstract condition validator.Until this is addressed, large quotes, large catalogs, and shops with many active rules using attribute-based conditions are subject to major performance degradation at scale. And I'll show you what I mean by leaving a screenshot of one transaction trace captured in New Relic.
I am showing a 3rd party extension here but please don't close the ticket on account of it! Study the trace and you'll see it leads into the core. And I was also able to reproduce the problem without this vendor integration.