LazyCache prevent null items being added to cache

1k Views Asked by At

I have a method that will expire null items immediately, however I wanted to know if there w as better way to do this for all memory cache items instead of repeating the same code over and over

output = _cache.GetOrAdd("GetRecordUri" + 123, entry =>
{
    var record = internalGetRecordUri();
    if (record == null)
        // expire immediately
        entry.AbsoluteExpirationRelativeToNow = new TimeSpan(-1, 0, 0, 0);
    else
        entry.AbsoluteExpirationRelativeToNow = new TimeSpan(1, 0, 0, 0);
    return record;
});

The code in bold seems redundant Is there an extension that I can use that will do the same?

2

There are 2 best solutions below

5
On BEST ANSWER

You can place this check in separate method:

public void SetAbsoluteExpiration(Entry entry, object value) // change Entry to correct type
{
    if (value is null) // or if (value == null)
        // expire immediately
        entry.AbsoluteExpirationRelativeToNow = new TimeSpan(-1, 0, 0, 0);
    else
        entry.AbsoluteExpirationRelativeToNow = new TimeSpan(1, 0, 0, 0);
}

And call it everywhere you need:

 output = _cache.GetOrAdd(
    "GetRecordUri" + 123, entry => {
        var record = internalGetRecordUri();
        
        SetAbsoluteExpiration(entry, record);

        return record;
    });
0
On

It would be nice if you could signal in addtemFactory that the value is not to be cached at all, e.g.

output = _cache.GetOrAdd("GetRecordUri_" + id, entry =>
{
    var record = internalGetRecordUri(id);
    if (IsError(record))
        entry.IsValidToCache = false; //  not actual
    return record;
});

But there is no such mechanism, without throwing an exception.

Setting the AbsoluteExpirationRelativeToNow to a zero or negative value does not work, it throws a ArgumentOutOfRangeException:

System.ArgumentOutOfRangeException
  Message=The relative expiration value must be positive. (Parameter 'AbsoluteExpirationRelativeToNow')
Actual value was 00:00:00.
  Source=Microsoft.Extensions.Caching.Memory
  StackTrace:
   at Microsoft.Extensions.Caching.Memory.CacheEntry.set_AbsoluteExpirationRelativeToNow(Nullable`1 value)

Throwing an exception in the addtemFactory, is however supported and effective to prevent caching of the result: "LazyCache Stops you inadvertently caching an exception by removing Lazys that evaluate to an exception". I recommend using a more meaningful exception type than a ArgumentOutOfRangeException

e.g.

output = _cache.GetOrAdd("GetRecordUri_" + id, entry =>
{
    var record = internalGetRecordUri(id);
    if (IsError(record))
        throw new SomeException("GetRecordUri failed for " + id); // actual
    return record;
});

You just have to now think about where the exception is caught.