ZiggyCreatures / FusionCache

FusionCache is an easy to use, fast and robust hybrid cache with advanced resiliency features.
MIT License
1.65k stars 87 forks source link

[BUG] Setting the entry in memory cache from distributed cache doesn't respect original options #171

Closed vsilvar closed 1 year ago

vsilvar commented 1 year ago

Describe the bug When retrieving a cached entry, which doesn't exist in memory cache, but does exist in distributed cache, the original options are not respected.

To Reproduce Here's a MRE (Minimal Reproducible Example) of the issue:

public async ValueTask<string> GetToken()
{
    var cacheEntry = await _cache.TryGetAsync<string>("token");
    if (cacheEntry.HasValue)
    {
        return cacheEntry.Value;
    }

   // Retrieved from external API for example
    var (token, expiration) = ("token-value", TimeSpan.FromMinutes(5));

    await _cache.SetAsync(token, new FusionCacheEntryOptions(expiration));
    return token;
}

Expected behavior I would expect that when the entry is set in the memory cache, it would do so with the original options, assuming they aren't being explicitly set when calling TryGetAsync

Versions I've encountered this issue on:

Additional context Let's assume a scenario with 2 servers, A and B:

Instead of using the duration that was initially provided, it will use the duration passed to the TryGetAsync method or the default if nothing is passed. A possible fix would be to also pass the duration when calling TryGetAsync, but in this case, we can't even determine which should be the correct duration, because it's dependent on the actual entry.

I would assume that the original options would be retained, when adding the item to memory cache from the distributed cache, unless specifically overridden.

vsilvar commented 1 year ago

In this scenario, ideally it would even use the TTL on the distributed cache as the duration for setting the memory cache. But not sure how feasible that actually is.

jodydonetti commented 1 year ago

Hi @vsilvar and thanks for using FusionCache!

In FusionCache the entry options used are the ones specified in each call: if none are specified then the normal flow is that the so called DefaultEntryOptions (defined once for an entire cache instance, and used as a default starting point) are duplicated and used.

This means that entry options defined on another cache node are not transmitted, nor saved in the distributed cache.

Having said that, there's one exception to this rule: the expiration.

If you look here at the test named MemoryExpirationAlignedWithDistributedAsync you can see that in fact it already works like you desire.

If you still have troubles with this please provide me with a MRE and I'll happily try to understand what is the issue.

Thanks.

jodydonetti commented 1 year ago

Closing this for now, if new informations will come I can always re-open it.