Skip to content

[BUG] Performance issue regarding BO loading #152

Open
@bhennesAdv

Description

@bhennesAdv

Description

Hello,

I faced a memory limit issue on the backoffice customer view because the customer has an high number of orders (more than 1000) with an high number of product.

As the CustomerChecker to allow customer erase loads them all, the requirement memory is higher than the 4G allowed.
Class :
https://github.com/opengento/magento2-gdpr/blob/master/Model/Customer/CustomerChecker.php

Prerequisites

PHP Version:

  • 8.3

Magento Version:

  • 2.4.7-p4

Module Version:

  • 4.4.2

Desktop (if applicable):
NA

Smartphone (if applicable):
NA

Issue Details

As OrderRepositoryInterface is used to load the full collection of orders (and their content) an high amount of order consumes an high amount of memory (to count them)

Steps to reproduce the behavior

  1. Create a customer with an high number of complex orders
  2. Click on the customer view access on the backoffice customer grid
  3. See error

Expected behavior
A count check should not impact to heavily the loading of the customer view

Screenshots

Additional context
I do understand that using OrderRepositoryInterface is a good practice in the magento ecosystem.
I only think that it's not adapted when you only want to count the number of orders.
There is a pretty strong performance enhancement by just using an OrderCollectionFactory and calling getSize() instead of loading the entire collection with all the child data.

In addition to that, as the class is final, plugins cannot be declared to add the wanted behavior properly.

Here is the preference I've implemented which works with my current volume.

<?php
/*
 * Copyright Blablabla
 */

namespace CustomerDomain\Customer\Preference\Gdpr\Model\Customer;

use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory as CollectionFactory;
use Opengento\Gdpr\Model\Config;
use Opengento\Gdpr\Model\Entity\EntityCheckerInterface;

/**
 * We need to reimplement the checker because it loads all orders data
 * and this is causing memory limit issue for customer with more than 1000 orders
 */
class CustomerChecker implements EntityCheckerInterface
{
    /**
     * @var bool[] Local cache for the values
     */
    private array $cache;

    /**
     * Constructor
     *
     * @param CollectionFactory $orderCollectionFactory
     * @param Config $config
     */
    public function __construct(
        private readonly CollectionFactory $orderCollectionFactory,
        private readonly Config $config
    ) {
        // Nothing to do here
    }

    /**
     * @inheritDoc
     */
    public function canErase(int $entityId): bool
    {
        if (!isset($this->cache[$entityId])) {
            $this->cache[$entityId] = (0 === $this->orderCollectionFactory->create()
                    ->addFieldToFilter(OrderInterface::STATE, ['nin' => $this->config->getAllowedStatesToErase()])
                    ->addFieldToFilter(OrderInterface::CUSTOMER_ID, ['eq' => $entityId])
                    ->getSize());
        }

        return $this->cache[$entityId];
    }
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions