Products provider and caching strategies

Tags: 219 views 0

How to configure products fetching in GUI applications (Atomia Store and User Panels) to use caching with the desired strategy.

Overview

Products provider is a helper class used for retrieving products from Billing. Whenever products are needed in GUI applications this helper is used. The interface for all implementations’ IProductsProvider exists in the Atomia.Web.Plugin.ProductsProvider library together with some implementations.

Currently, there are four implementations of products provider which can be used. They can be split into two groups:

  1. Shops products’ providers
  2. XML hosting file products’ providers

Keep in mind

Since the 16.9 release all Atomia applications are configured to use Shops. Therefore, this is preferred and the XML files of hosting products will be removed in the future. If you haven’t migrated to shops we recommend doing it following our Migrate To Shops guide.

There are two implementations of products provider which use shops:

  1. BillingApiShopProductsProvider – Used in User panels.
  2. PublicApiShopProductsProvider – Used in the Store and Order Website.

Caching strategies

Since shops can contain a lot of products which are not changed very often they are cached in Atomia applications. GUI applications have their own cache for storing shop products and checking with the underlying API whether the cache items are expired or not. When products or shops are updated in the Admin Panel and the cache is flushed there are two strategies for refreshing the products’ caches in the GUI applications:

  1. SimpleLockingCachingStrategy – Flushes the complete cache when it is expired and loads products when requested. This means that when the caches are flushed the first request will try to get a fresh set of products while other requests are waiting for it. With this strategy there is some waiting time after the cache flush, but the customers get fresh products only. This strategy is good for a smaller number of products or when updates are very rare and timed to happen during a period with lower traffic.
  2. NonBlockingRefreshCachingStrategy – Never causes any waiting time when the cache is flushed. It will try to refresh the products list in the background but continues to serve the requestor’s old set of items until it is refreshed. This means that the customers always get their products, but that the products are stale right after the caches have been flushed in the Admin Panel.

Keep in mind

Keep in mind that Atomia GUI applications are using Enterprise Library Caching Application Block which has in memory cache. Therefore, any restart of the IIS, website, or application pool will also reset the caches completely, meaning the applications will have to wait for an initial load of products.

Configuration

User Panels and Admin Panel

The configuration is stored in the applications’ web.config file in the unity section. The applications are preconfigured to use BillingApiShopProductsProvider with NonBlockingRefreshCachingStrategy. For caching, Enterprise Library Caching is used with ProductsCache as the underlying cache:

<typeAliases>
  <typeAlias alias="IProductsProvider" type="Atomia.Web.Plugin.ProductsProvider.IProductsProvider, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="BillingApiShopProductsProvider" type="Atomia.Web.Plugin.ProductsProvider.BillingApiShopProductsProvider, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="BillingApiXmlProductsProvider" type="Atomia.Web.Plugin.HostingProducts.Helpers.BillingApiXmlProductsProvider, Atomia.Web.Plugin.HostingProducts" />
  <typeAlias alias="ICachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.ICachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="SimpleLockingCachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.SimpleLockingCachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="NonBlockingRefreshCachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.NonBlockingRefreshCachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="ICachingManager" type="Atomia.Web.Plugin.ProductsProvider.ICachingManager, Atomia.Web.Plugin.ProductsProvider" />
  <typeAlias alias="HttpApplicationStateCacheManager" type="Atomia.Web.Plugin.HostingProducts.Helpers.HttpApplicationStateCacheManager, Atomia.Web.Plugin.HostingProducts" />
  <typeAlias alias="EntLibCachingManager" type="Atomia.Web.Plugin.ProductsProvider.EntLibCachingManager, Atomia.Web.Plugin.ProductsProvider" />
</typeAliases>

<containers>
  <container>
    <register type="EntLibCachingManager">
      <constructor>
        <param name="cacheManagerName" value="ProductsCache" />
      </constructor>
    </register>
    <register type="SimpleLockingCachingStrategy">
      <constructor>
        <param name="cachingManager" />
      </constructor>
    </register>
    <register type="NonBlockingRefreshCachingStrategy">
      <constructor>
        <param name="cachingManager" />
        <param name="cacheRefreshTimeoutInSeconds" value="60" />
      </constructor>
    </register>
    <register type="ICachingManager" mapTo="EntLibCachingManager" />
    <register type="ICachingStrategy" mapTo="NonBlockingRefreshCachingStrategy" />
    <register type="IProductsProvider" mapTo="BillingApiShopProductsProvider">
      <constructor>
        <param name="useIdentityDelegation" value="false" />
        <param name="cachingStrategy" />
      </constructor>
    </register>
  </container>
</containers>

To use the SimpleLockingCachingStrategy caching strategy, replace NonBlockingRefreshCachingStrategy with SimpleLockingCachingStrategy:

<register type="ICachingStrategy" mapTo="NonBlockingRefreshCachingStrategy" /> 

Another configurable option is cacheRefreshTimeoutInSeconds for NonBlockingRefreshCachingStrategy. This value represents for how long (in seconds) the application will wait for the refresh procedure to fetch new data from the API before trying again. For shops with lots of items this value should be increased.

Atomia Store

The configuration is stored in the application’s web.config file in the unity section. Since Store is using the Public API, it is configured to use PublicApiShopProductsProvider with NonBlockingRefreshCachingStrategy. For caching, Enterprise Library Caching is used with ProductsCache as the underlying cache:

<alias alias="IProductsProvider" type="Atomia.Web.Plugin.ProductsProvider.IProductsProvider, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="PublicApiShopProductsProvider" type="Atomia.Web.Plugin.ProductsProvider.PublicApiShopProductsProvider, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="AtomiaBillingPublicService" type="Atomia.Web.Plugin.OrderServiceReferences.AtomiaBillingPublicService.AtomiaBillingPublicService, Atomia.Web.Plugin.OrderServiceReferences" />
<alias alias="ICachingManager" type="Atomia.Web.Plugin.ProductsProvider.ICachingManager, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="HttpApplicationStateCacheManager" type="Atomia.Web.Plugin.HostingProducts.Helpers.HttpApplicationStateCacheManager, Atomia.Web.Plugin.HostingProducts" />
<alias alias="EntLibCachingManager" type="Atomia.Web.Plugin.ProductsProvider.EntLibCachingManager, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="ICachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.ICachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="SimpleLockingCachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.SimpleLockingCachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
<alias alias="NonBlockingRefreshCachingStrategy" type="Atomia.Web.Plugin.ProductsProvider.NonBlockingRefreshCachingStrategy, Atomia.Web.Plugin.ProductsProvider" />
<container>
  <register type="AtomiaBillingPublicService">
    <property name="Url" value="http://orderapi.dev.atomia.com/AtomiaBillingPublicService.asmx" />
    <property name="Timeout" value="600000" />
  </register>
  <register type="EntLibCachingManager">
    <constructor>
      <param name="cacheManagerName" value="ProductsCache" />
    </constructor>
  </register>
  <register type="SimpleLockingCachingStrategy">
    <constructor>
      <param name="cachingManager" />
    </constructor>
  </register>
  <register type="NonBlockingRefreshCachingStrategy">
    <constructor>
      <param name="cachingManager" />
      <param name="cacheRefreshTimeoutInSeconds" value="60" />
    </constructor>
  </register>
  <register type="ICachingManager" mapTo="EntLibCachingManager" />
  <register type="ICachingStrategy" mapTo="NonBlockingRefreshCachingStrategy" />
  <register type="IProductsProvider" mapTo="PublicApiShopProductsProvider">
    <constructor>
      <param name="publicService" />
      <param name="cachingStrategy" />
    </constructor>
  </register>
</container>

To use the SimpleLockingCachingStrategy caching strategy, replace NonBlockingRefreshCachingStrategy with SimpleLockingCachingStrategy:

 <register type="ICachingStrategy" mapTo="NonBlockingRefreshCachingStrategy" /> 

Another configurable option is cacheRefreshTimeoutInSeconds for NonBlockingRefreshCachingStrategy. This value represents for how long (in seconds) the application will wait for the refresh procedure to fetch new data from the API before trying again. For shops with lots of items this value should be increased.

Was this helpful?