Developer forum

Forum » CMS - Standard features » Cache issues
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Hi there,

I have a site running 9.18.0 that is regularly failing on getting a currency from the cache. When it fails, I see the following stack trace:

System.ArgumentNullException: Value cannot be null.
Parameter name: key
at System.Collections.Concurrent.ConcurrentDictionary`2.TryGetValue(TKey key, TValue& value)
at Dynamicweb.Caching.DictionaryCache`2.GetCacheResult(IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(TKey key)
at Dynamicweb.Ecommerce.ProductCatalog.ViewSettingsBaseCurrencyBase`1.GetCurrency()
at Dynamicweb.Ecommerce.ProductCatalog.ViewSettingsBaseCurrencyBase`1.GetPriceContext()
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrice(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Lazy`1 priceInfo)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__49()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at CompiledRazorTemplates.Dynamic.RazorEngine_54bb315f40d545b283e52306beddefc3.Execute() 

What it looks like is that it's failing because the code tries to look up a currency by a null-code; i.e. the requested cache key is null rather than the returned item  .

It could be custom code maybe but we're seeing the same thing in the backend too. When it happens, opening the Orders list under Ecommerce gives me this:

[ArgumentNullException: Value cannot be null.
Parameter name: key]
   System.Collections.Concurrent.ConcurrentDictionary`2.TryGetValue(TKey key, TValue& value) +14397390
   Dynamicweb.Caching.DictionaryCache`2.GetCacheResult(IEnumerable`1 keys) +347
   Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys) +143
   Dynamicweb.Caching.ServiceCache`2.GetCache(TKey key) +104
   Dynamicweb.Ecommerce.Orders.Order.get_Currency() +49
   Dynamicweb.Ecommerce.Orders.OrderLineService.GetByOrder(Order order) +286
   Dynamicweb.Ecommerce.Orders.Order.get_OrderLines() +155
   Dynamicweb.Admin.UCOrderList.GetListRow(OrderSearchResultItem backendOrder, Int32 index) +2114
   Dynamicweb.Admin.UCOrderList.FillList() +497
   Dynamicweb.Admin.UCOrderList.LoadList() +848

All orders in the database have a valid currency code and none of them is null. What's even more confusing is that the problem seems to solve itself. The problem goes away by itself, only to return again a bit later.

Could it be related to import jobs that may be clearing the cache? Is there anything I can look at or debug to further troubleshoot this?

Imar


Replies

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

1. Missing currency?

Do you have any orders in the database where [EcomOrders].[OrderCurrencyCode] doesn't exist in [EcomCurrencies].[CurrencyCode]?

2. Cache issue?

If there is an import of currencies then make sure that it clears the currency cache after the import is done.

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Thanks Morten,

>> Do you have any orders in the database where [EcomOrders].[OrderCurrencyCode] doesn't exist in [EcomCurrencies].[CurrencyCode]?

Nope. All orders in the database have a valid currency code and none of them is null. This query gives me zero results:

SELECT * FROM EcomOrders WHERE OrderCurrencyCode NOT IN (SELECT CurrencyCode FROM EcomCurrencies) OR COALESCE(OrderCurrencyCode, '') = ''

>> If there is an import of currencies then make sure that it clears the currency cache after the import is done.

Nope, we don't import currencies.

Also: note that this is intermittent; after a while it's gone again, which I think it's not a database data issue, but something in memory / cache.

Imar

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

The first stack gets the currency from an order object directly - the second stack gets the currency from context.

The only thing I can see they can have in common is that something is writing to Common.Context.Currency. So check if you have anything custom touching that.

Another could be ?CurrencyCode=<somethingInvalid> is touching the context - but should only react if a valid currency code is used.

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

I think I found it. We had some template code that changes the currency code of the context (I have no idea why it would that and why it only changed the code, not the entire currency) that looked like this:

Context.Currency.Code = GetSomeValue();

Under certain conditions, GetSomeValue() would return null, which then wiped out the code on the existing currency. Woopps. Maybe this should have been an immutable property with an internal setter?

Imar

 

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Imar

Thanks for reporting back.

Not sure we can change the Currency.Code property for compatibility reasons. It would be a breaking change causing templates not to compile...

We might be able to throw an exception if it is set to null or empty string.

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Fair enough. An exception on null would be helpful; although I do admit this is all a bit of an edge case anyway.

 

 

You must be logged in to post in the forum