Skip to content

Magento_Persistent performance overhead on non-cart, non-checkout pages #39948

Open
@adamwaclawczyk

Description

@adamwaclawczyk

Summary

Preconditions (*)

  1. Products added to cart

Steps to reproduce (*)

  1. Enter PDP with profiler enabled
  2. Quote is not expired and the quote is fully loaded to check this, performance suffers

Expected result (*)

  1. persistent_quote observer does not load the quote before it's absolutely necessary

Actual result (*)

  1. persistent_quote is loading the full quote with expensive assignProducts function call

Magento_Persistent adds controller_action_predispatch event persistent_quote observer. On non-cart, non-checkout pages(e.g. PDP) it's loading quote and it impacts the TTFB significantly. Due to the observer's private function declarations, overriding the logic inside the observer class requires developers to add class preference or patch the observer class directly. There is no "ok" way to implement workaround for this.

Image


return (bool)$this->getQuote()->getIsPersistent();

Both of these calls could be simplified by checking the quote table data directly. The business logic will still be satisfied. If the quote has to be expired, then the quote probably needs to be still loaded fully.

Examples

class QuoteResourceWrapper
{
    public function __construct(
        private readonly ResourceConnection $resourceConnection
    ) {
    }

    public function isActive(?int $quoteId): bool
    {
        if (empty($quoteId)) {
            return false;
        }
        $table = $this->resourceConnection->getTableName('quote');
        $connection = $this->resourceConnection->getConnection();
        $select = $connection->select()
            ->from($table, 'is_active')
            ->where('entity_id = ?', $quoteId);

        return $connection->fetchOne($select) == true;
    }

    public function isPersistent(?int $quoteId): bool
    {
        if (empty($quoteId)) {
            return false;
        }
        $table = $this->resourceConnection->getTableName('quote');
        $connection = $this->resourceConnection->getConnection();
        $select = $connection->select()
            ->from($table, 'is_persistent')
            ->where('entity_id = ?', $quoteId);

        return $connection->fetchOne($select) == true;
    }
}

Proposed solution

Do not load quote fully if not needed.
I have prepared a sample class that could be used as a wrapper for getting the required data instead, see Examples

Release note

No response

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: FrameworkComponent: PersistentIssue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedPriority: P3May be fixed according to the position in the backlog.Reported on 2.4.xIndicates original Magento version for the Issue report.Reproduced on 2.4.xThe issue has been reproduced on latest 2.4-develop branchTriage: Dev.ExperienceIssue related to Developer Experience and needs help with Triage to Confirm or Reject it

    Type

    No type

    Projects

    Status

    Ready for Development

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions