Frequency of delivery service decorator being called

How to configure and adapt Aimeos based shops as developer
Forum rules
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
BrianMecler
Posts: 41
Joined: 03 Jun 2023, 17:30

Frequency of delivery service decorator being called

Post by BrianMecler » 26 Jul 2023, 14:22

Hello,

Laravel Framework 10.13.1, php8.1-fpm, aimeos/aimeos-laravel 2023.04.2

I created 3 delivery services from the Admin: FedEx Ground, FedEx 2 Day, FedEx Overnight
I created a single Decorator called FedEx and applied it to each of these services.
The service has a beConfig called 'serviceType' where I pass ground, 2day, overnight to the decorator to be used in the calcPrice function
The calcPrice function calls the FedEx API and uses the serviceType to get the price of each service

I am trying to figure out: how many times does the calcPrice method in my decorator get called? And how can I limit the number of times I am hitting the FedEx API?

I see that when I add a product to the basket it gets called, twice, which makes sense to me:

Call 1:
\blueperch\src\MShop\Service\Provider\Decorator\FedEx.php:48)
\aimeos\aimeos-core\src\MShop\Plugin\Provider\Order\Autofill.php:236)


Call 2:
\blueperch\src\MShop\Service\Provider\Decorator\FedEx.php:48)
\aimeos\aimeos-core\src\MShop\Plugin\Provider\Order\ServicesUpdate.php:105)

When I proceed to the Address portion of checkout its called at least 3 times, once for each of the services I defined
When I proceed to the Delivery portion of checkout its called at least 3 times, once for each of the services I defined (this I understand because I want to display the price of each on the delivery page)
When I proceed to the Payment portion of checkout its called at least 3 times, once for each of the services I defined

So as you can see, I am hitting the FedEx API over 10 times in the checkout process.. which is slow

Have I implemented this correctly?

Is there a way I should check where the calcPrice function call is coming from, and then conditionally run the API calls?

Maybe I should actually be intercepting a different function, not calcPrice? Or conditionally intercepting different functions somehow?

As always, your help is greatly appreciated.

User avatar
aimeos
Administrator
Posts: 7894
Joined: 01 Jan 1970, 00:00

Re: Frequency of delivery service decorator being called

Post by aimeos » 27 Jul 2023, 06:18

Yes, the delivery service including its decorators is called several times during the checkout due to the event system used for the basket. Whenever an address/service/product is added/changed/removed from the basket, an event notifies the basket plugins about the change and they can then modify the basket themselves. This leads to several calls for calcPrice().

To avoid performance issues, you should only send an request to the FedEx API if a relevant content in the basket changes (most often: products or product amounts) and store a hash for comparing the baskets in the session using:

Code: Select all

$this->context()->session()->set( 'myplugin/<basket type>/hash', '...' );
// retrieve hash
$this->context()->session()->get( 'myplugin/<basket type>/hash' );
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

BrianMecler
Posts: 41
Joined: 03 Jun 2023, 17:30

Re: Frequency of delivery service decorator being called

Post by BrianMecler » 28 Jul 2023, 12:39

Hello Again,

I must have problems in my thought process or logic here..

My code consists of this in my decorator:

Code: Select all

	public function calcPrice( \Aimeos\MShop\Order\Item\Iface $basket, array $options = [] ) : \Aimeos\MShop\Price\Item\Iface
	{
		// do something before
		$price = $this->getProvider()->calcPrice( $basket );
		// do something after
		
		...create the hash and store it..
		
		// if the hash changed then call the FedEx API again
		if ($stored_hash <> $hash) {
			$cost = the price i got from the fedex API;
			$price->setCosts($cost);
			return $price;
		}
		
		// If the hash didnt change, then what?

		return $price;
	}
When multiple calls start getting made to calcPrice(), and the API call gets skipped because the hashes match, and the $price doesnt have a cost again. I was expecting that the $price->cost would persist across all the calls to calcPrice().

I tried doing this when the code gets skipped for the API call in an attempt to persist the shipping costs:

Code: Select all

	// If the hash didnt change, then what?
	$price->setCosts($basket->getPrice()->getCosts());
	return $price;
That got me a little further, but the shipping costs end up getting reset back to $0 when I manually navigate back and forth through the checkout process tabs on the web interface.

Do I need to somehow manually save the basket or order after I set a cost in calcPrice()?

User avatar
aimeos
Administrator
Posts: 7894
Joined: 01 Jan 1970, 00:00

Re: Frequency of delivery service decorator being called

Post by aimeos » 29 Jul 2023, 06:54

You must store the calculated shipping costs returned by the FedEx API in the session too and return it if the FedEx API isn't called.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

BrianMecler
Posts: 41
Joined: 03 Jun 2023, 17:30

Re: Frequency of delivery service decorator being called

Post by BrianMecler » 29 Jul 2023, 12:27

Thank you, when you reference the following code:

Code: Select all

$this->context()->session()->set( 'myplugin/<basket type>/hash', '...' );
What is <basket type>? Is this the mini basket vs standard basket? or something in relation to the ability to save baskets?

User avatar
aimeos
Administrator
Posts: 7894
Joined: 01 Jan 1970, 00:00

Re: Frequency of delivery service decorator being called

Post by aimeos » 31 Jul 2023, 09:15

Noticed, that the basket type is only used in the basket frontend controller but it's not part of the basket itself. Thus, you may ignore that detail or use the hashes as key for the price, e.g.:

Code: Select all

$this->context()->session()->set( 'myplugin/<hash>', '99.00' );
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

Post Reply