Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Improve large cart performance

Describes how to optimize large carts to handle smoothly.

Optimizely has identified several points in the handler chains or public surface area that would significantly improve performance for large cart order submissions and reduce the time to modify large carts. While this code will be included in a forthcoming release, this article allows you to implement the code now to improve these performance issues.

Order Submit (inventory modification)

This is the first part of the Order Submit process you loop through. You can reduce tracked inventory for products and shift quote required products to a status of QuoteRequested happens in step 2400 ProcessInventory of the UpdateCart API handler. See Cart API Handler.

If you do not track inventory in Configured Commerce because you have full real-time inventory and do not utilize quote requests as a part of the storefront, you can replace this step by moving to the next piece in the chain:

return this.NextHandler.Execute(unitOfWork, parameter, result);

You can confirm that you have full real-time inventory by filtering products with the TrackInventory flag.

Order Submit (order history generation)

After you submit the order to the ERP, you again cycle through all cart items to generate the order history in step 3300 CreateOrderHistory of the UpdateCart API handler. This step is necessary, but you do not need to complete it in real-time while waiting for the API call to finish.

You can view an updated version of the 3300 CreateOrderHistory handler below. This version is based on the current code (2303) and should be applicable to almost all cloud customers as the code has not been changed substantively in 5.0+ versions. This code continues on with a part of the chain, rather than wait for the process to finish.

namespace Insite.Cart.Services.Handlers.UpdateCartHandler {
using System;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using Insite.Cart.Services.Parameters;
using Insite.Cart.Services.Pipelines;
using Insite.Cart.Services.Pipelines.Parameters;
using Insite.Cart.Services.Results;
using Insite.Common.Dependencies;
using Insite.Common.Logging;
using Insite.Core.Interfaces.Data;
using Insite.Core.Interfaces.Dependency;
using Insite.Core.Services;
using Insite.Core.Services.Handlers;
using Insite.Data.Entities;
using Insite.Data.Extensions;
[DependencyName(nameof(CreateOrderHistory))] public sealed class CreateOrderHistory: HandlerBase < UpdateCartParameter, UpdateCartResult > {
  public override int Order => 3300;private readonly Lazy < ICartPipeline > cartPipeline;public CreateOrderHistory(Lazy < ICartPipeline > cartPipeline) {
    this.cartPipeline = cartPipeline;
  }
  public override UpdateCartResult Execute(IUnitOfWork unitOfWork, UpdateCartParameter parameter, UpdateCartResult result) {
    Task.Factory.StartNew(() => {
      try {
        var threadUnitOfWork = DependencyLocator.Current.GetInstance < IUnitOfWorkFactory > ().GetUnitOfWork();
        var cart = threadUnitOfWork.GetRepository < CustomerOrder > ().GetTable().Expand(o => o.OrderLines.Select(p => p.Product)).FirstOrDefault(o => o.Id == result.GetCartResult.Cart.Id);
        var createOrderHistoryParameter = new CreateOrderHistoryParameter {
          CustomerOrder = cart, Status = parameter.Status
      };
      var createOrderHistoryResult = this.cartPipeline.Value.CreateOrderHistory(createOrderHistoryParameter);
      if (createOrderHistoryResult.ResultCode != ResultCode.Success) {
        LogHelper.For(this).Error($"Unable to create order history: {createOrderHistoryResult.Message}");
      }
      threadUnitOfWork.Save();
      threadUnitOfWork.Close();
    } catch (Exception e) { 
        // don't allow any exception to bubble up and kill the worker process thread LogHelper.For(this).Error(e.Message, e); } }, TaskCreationOptions.LongRunning ); return this.NextHandler.Execute(unitOfWork, parameter, result); 
      } 
  } 
}

Cart (reordering lines)

In 5.1.2202, Optimizely added a new parameter to the RemoveCartLineParameter and RemoveCartLinesParameter chains called RenumberLines. Although this parameter defaults to True to mirror old logic and keep backwards compatibility intact, it is less performant. Setting this parameter to False makes the cart renumber lines online once at the end of the order process rather than continuously, which should increase performance of inline cart actions like deletes. You must set this parameter sometime before the RenumberCartLines step in the chains.

Contact your Customer Success Manager if you have any questions on ingesting this code to improve large cart performance.