Magento 2 Instant Purchase module throws a TypeError on Load Test
Published: 2021-09-03 05:20:45

I faced the below error when a load test was running, and it started to appear when around 10 users out of 50 are up on load test (initial LT round).

`TypeError: Uncaught exception 'TypeError' with message 'Argument 2 passed to Magento\InstantPurchase\Model\PaymentMethodChoose\LastCreatedPaymentTokenChooser::buildSearchCriteria() must be of the type integer, null given, called in /var/www/magento/vendor/magento/module-instant-purchase/Model/PaymentMethodChoose/LastCreatedPaymentTokenChooser.php on line 78' in /var/www/magento/vendor/magento/module-instant-purchase/Model/PaymentMethodChoose/LastCreatedPaymentTokenChooser.php:92`

This error was not appearing when it was testing manually.
Could be something to do with session storage on server, but I couldn't identify such. Redis max_concurrency was set to 20 in `app/etc/env.php` as well.

So when I was checking the code, `Magento\InstantPurchase\CustomerData\InstantPurchase` class takes `Magento\Customer\Model\Session` as a constructor parameter. Since this dependent Customer Session class has a bit lengthy constructor injection list itself, and by the nature of it, it loads all of them in its constructor as well, I thought sometimes it could be the problem so I used a proxy class to load it. I have seen in most places people load `Magento\Customer\Model\SessionFactory` class, when they have issues loading customer session when cache enabled but the purpose of the singleton usage of that class is kind of lost. So it's always better to use Proxy class.

Back to the original problem.. 
Below is how I injected proxy class into `Magento\InstantPurchase\CustomerData\InstantPurchase`

Created a custom module and using `di.xml` I included this;

    <type name="Magento\InstantPurchase\CustomerData\InstantPurchase">
        <arguments>
            <argument name="customerSession" xsi:type="object">Magento\Customer\Model\Session\Proxy</argument>
        </arguments>
    </type>

Then ran the load test again for 100 users. No errors appeared. Earlier it was throwing the error when it started to hit 10 users. 

But then, we ran a load with 700 users, then again the error started to appear. No idea why, if anyone of you have any idea, please share. 

Then I had to use an around plugin like this;
Added this in `di.xml`

    <type name="Magento\InstantPurchase\CustomerData\InstantPurchase">
        <plugin name="vendor_instant_purchase_cutomerdata_around" type="Vendor\CustomerSectionLoadFix\Plugin\CustomerData\InstantPurchaseAround" />
    </type>

`app/code/Vendor/CustomerSectionLoadFix/Plugin/CustomerData/InstantPurchaseAround.php`

```
<?php

namespace Vendor\CustomerSectionLoadFix\Plugin\CustomerData;

use Closure;
use Magento\Customer\Model\Session;
use Magento\InstantPurchase\CustomerData\InstantPurchase;

class InstantPurchaseAround
{
    /**
     * @var Session\Proxy
     */
    private $customerSession;

    /**
     * InstantPurchaseAround constructor.
     * @param Session\Proxy $customerSession
     */
    public function __construct(Session\Proxy $customerSession)
    {
        $this->customerSession = $customerSession;
    }

    /**
     * @param InstantPurchase $subject
     * @param Closure $proceed
     * @return array
     */
    public function aroundGetSectionData(
        InstantPurchase $subject,
        Closure $proceed
    ) {
        if (!$this->customerSession->getCustomer()->getId()) {
            return ['available' => false];
        }

        return $proceed();
    }
}

Please let me know if a you guys have a better solution