It has been 5 years since I started Pro Episerver Commerce back in early 2016. The book was a success, not as big as I hoped for, but definitely bigger than I expected. Tackling a niche market, it was fairly popular within the community, and it gave me a lot of happiness (and some pocket changes) to see that it helped many developers to understand and use the framework – which I help created, and love – better.
So much has changed in the last 5 years.
I have my first kid, and a second one. I left Commerce development team, to work on my own, then have a small team. Episerver bought Optimizely, then rebrand.
And so much more has happened with Episerver Commerce, more than just being renamed to Optimizely Commerce Cloud.
It deserves a new book!
To celebrate my 10th anniversary with Episerver (now Optimizely), I am proud, and excited to announce the second edition of Pro Episerver Commerce – Pro Optimizely Commerce Cloud. Most of the content written in Pro Episerver Commerce is still very much applicable, but I feel there is a need to refocus and expand on important parts.
Recently (as recent as this morning) I was asked to look into a case when the Find indexing performance was subpar. Upon investigation – looking at a properly captured trace from dotTrace – it was clear that at least 30% percent of time was spending in loading the CatalogDto
This is something that should not happen, as the CatalogDto should have been cached. Also, a normal site should have very few catalogs, so the cache should be very effective. However, data does not lie – it has been hitting database a lot, and a quick check on the site settings revealed that the entire DTO cache has been indeed, disabled
By setting these timeout settings to 0, the cache is immediately invalidated, rendering them useless. The CatalogDto, therefore, is loaded everytime from database, causing the bottleneck.
The reason for setting those timeout to 0 was probably – I guess – to reduce the memory footprint of the site. However, Catalog DTOs are fairly small in size, and since Commerce 11, it has been smart enough to skip caching the DTOs if there is cache on a higher (content ) level, thanks to my colleague Magnus Rahl. So DTOs should not be of any concerns, if you are not actively using them (and in most of the case, you should not). By re-enabling the cache, the indexing time can be cut, at least 30%, according to the aforementioned trace.
As you might wonder, Catalog content provider still uses the DTOs internally, therefore it would load those for data.
Moral of the story:
The cache settings are there, but because you can, does not mean you should. I personally think cache settings should be as hidden as possible from accidental changes. Disabling cache, and in a lesser extend, changing default cache timeout, can have unforeseeable consequences. Only do so if you have strong reasons to do so. Or better, let us know why you need to do that, and we can figure out a compromise.
It has been a while since I write something in my blog – have been “fairly” busy making Commerce even faster for a while. But I should take a break from time to time and share things that will benefit community as a whole – and this is one of that break.
The Related Entries tab is generated for content with implements IAssociating interface. Bad news is EntryContentBase implements that interface, so each and every entry type you have, has that tab. But good news is we can override the implementation – by just override the property defined by IAssociating.
I have some more time to revisit the query now, and I realized I made a “small” mistake. The “optimized” query is using a Clustered Index Scan
So it’s not as fast as it should be, and it will perform quite poorly in no cache scenario (when the buffer is empty, for example) – it takes about 40s to complete. Yes it’s still better than the original one, both in non cached and cached cases. But it’s not good enough. An index scan, even cached, is not only slower, but also more prone to deadlocks. It’s also worse in best case scenario, when the original one can use the proper index seek.
It’s possible to run Quicksilver and ServiceAPI on a same site, with some modifications, as I blogged here. However, if you go down that path, there is something you must keep in mind: They are not using the same authentication mechanism.
I’ve seen issues where Quicksilver implementations have some WebAPI controllers, which were working fine until ServiceAPI is installed. The controllers started returning null for CustomerContext.Current.CustomerContact, and so on, breaking some functionalities. It’s bad, yes, but it happens because of reasons.
For a good long amount of time, workflows have been an essential part of Episerver Commerce (and even before that, Mediachase eCF). Once you get into order system, you just can’t escape workflows – because you need them. They handle many – if not all things, from validating items, checking inventories (to make sure that you are not selling something out-of-stock, or just discontinued (think of Galaxy Note 7, poor little shiny phone)), applying promotions, calculating taxes, process payments, and finally adjust inventories (yay, a customer places an order, let’s ship to him as soon as possible, firstly allocate the goods for him). And workflows are even required by later processing – when you complete the shipments (another happy customer!), or when you issue a return or an exchange (well, let’s keep the customer still happy).
It can be pretty confusing for new Commerce developers to understand how to work effectively with entries in Commerce. There are many things which represent the same concepts, however they are different and their APIs are not compatible. So which is which and what should you use?
Which is which
CatalogEntryDto is the DataSet to represent one or more entries (CatalogEntryDto can of course be empty). Beside the basic information like Name, Code, or MetaClassId, depends on how did you load it, a CatalogEntryDto can contain information about the assets, the associations or the variations (you can specify what to load by using CatalogEntryResponseGroup parameter. CatalogEntryDto, however, does not contain information of the metadata system of an entry – for example, if you add a metafield named “Description” to your entry metaclass – that is not available in a CatalogEntryDto. CatalogEntryDto can be loaded or saved by ICatalogSystem methods.
If you are using Catalog Search APIs for any customer-facing features, you are doing it wrong!
I have seen this problem a couple of times – the search feature on the site is “dead” – it is very slow, and the log file is usually filled with dead lock or timeout error. As it turns out, the search feature was implemented by Catalog Search APIs, which is a big no-no.
To be clear, there are two builtin APIs related to searching in Episerver Commerce: the “fast” one, which can be done via SearchManager, ISearchCriteria and ISearchResults, is the SearchProvider APIs. It’s the indexed search (strictly speaking, you can make it not “indexed”, but that’s beside the point), and the actual search functions will be provided by providers, like LuceneSearchProvider, Solr35SearchProvider, or FindSearchProvider.