commerce
commerce copied to clipboard
Available shipping methods are recalculated every time the order is retrieved
Description
One thing I have noticed with Commerce 3 is that it calls the shipping calculator a lot - basically every time an order is touched in anyway - front end or back end. Even console requests that do an elements query for orders. In particular, just viewing any order in the control panel sends a call to my (custom, very complicated) shipping calculator.
This doesn't make much sense to me - the order is completed so why does it need to call shipping again?
...Although I realise now that back end order creation/editing is a thing, so there has to be some mechanism in there for back end shipping calculations. But all this is of course a performance drag - which can be significant in some scenarios where we use live quotes etc, meaning it has to go off and hit an external API etc. We avoid a lot of it through caching of results (meaning basically instant return) - but that cache only lasts a few days (to match how long user carts last for) - not forever...so we tend to functionally notice this most when looking up older orders, which is just....a bit weird.
At the moment, I have put in some short circuits (like isConsoleRequest and checking isCompleted) - but it feels like a hack. And for example, if we're changing a completed order, we DO then need a shipping update... I can't find any relevant documentation really. Is there in fact an explicit way to know if the shipping needs re-calculating at a particular moment? Or any advice about this you might offer?
Additional info All versions up to date as of today. Custom shipping calculator...a bit of beast of a thing....
Could you cache the API request using a hash of the information used to make the api request?
This is what we do for the taxjar plugin:
https://github.com/craftcms/commerce-taxjar/blob/master/src/adjusters/TaxJar.php#L119-L141
That way if the completed order has not changed, no API request will be made.
Well, I do cache them...just not forever. I clear the cache regularly for a variety of reasons (e.g. shipping service price changes, and so that the cached quotes aren't older than any actual carts etc).
So I can't really currently cache things for the long term really - although I could adapt to doing that maybe - but I think the issue is more a bit general - e.g. those element queries during a console request that result in re-calcs etc. Seems a bit over eager and I don't really feel that caching is the real solve here.
This is only a performance issue because you are using a live rates API for the shipping method price, that's the expensive part.
Asking for the available shipping methods for an order with the built-in shipping calculator is otherwise fast.
I am guessing customers changing their shipping method after completing their order doesn't happen very often? Could you skip the live lookup if the order is completed? Maybe add a button on the order page that clears the custom shipping API cache for the order and retrieves the live rates again if they plan to change the shipping method of a completed order?
Will leave this ticket open and discuss internally if we can come up with a way to stop the availableShippingMethodoptions being called in a completed order context, a calling it in a lazy manor.
Oh sure, it's definitely the live rates that is the more significant part performance wise. But it's not really just that.
It just seems incorrect, more generally, to be re-calculating things (or calling for them to be re-calculated) - when it's not needed, and indeed not desired. And when there is perhaps some slight risk too - e.g. I am doing something else with orders as part of processing, and saving data to a field....if Commerce re-calculates shipping when I am not expecting it, and shipping rates have changed, and then as part of that I re-save the order....has the order data now changed?
Basically, my desire is that completed orders do not undergo any unnecessary or unpredictable re-calculations at any point, unless that is explicitly called for. And even if it isn't MUCH performance impact without the live rates, it's not necessarily nothing either - e.g. I am routinely dealing with 40 or 50 orders at a time, and even my non live rates shipping calculation stuff is quite complex as it involves grouping, boxing, retrieval of rates and zones (i.e. element queries) - and calculations. Per order, it's not so significant...but when dealing with a bunch of orders it becomes more so of course.
In our case, yes, the shipping method is indeed only very rarely changed on an order if they add or remove a product that changes the shipping category of the order (and in fact, we'll handle this in our downstream third party inventory/accounting, most likely, as the order will most likely have been pushed on when this happens...but sometimes we might get the chance to deal with it before that in Commerce).
I do think a 'lazy' (or really, on demand) approach is the way to go, if possible. It's definitely been a surprise to me to see the shipping calculator kick in (via the logging we do) - when doing all sorts of unrelated things to do with orders.
+1