Replies: 2 comments
-
The fundamental problem with doing sliding expiration, within all of our current expiration operators, is that they have no way of knowing when an item is accessed.
What I would do to implement this is actually decorate the public static IObservableCache<TObject, TKey> WithSlidingExpiration<TObject, TKey>(
this ISourceCache<TObject, TKey> source,
Func<TObject, TimeSpan?> lifetimeSelector,
TimeSpan? pollingInterval = null,
IScheduler? scheduler = null)
where TObject : not null
where TKey : not null; The existing Would happily take a PR for this, if you feel like doing one. |
Beta Was this translation helpful? Give feedback.
-
I've had no time to work on this problem, but now my application has production incidents reported because of the absolute cache expiration, so I had to come up with a quick solution. Besides the actual cache holding the business objects I introduced a last access cache with absolute expiration. Upon object retrieval I update the last access cache, so the absolute expiration gets recalculated. Should an item expire from the last access cache, I remove it from the original cache. This solution seems to work for my case. Here are the relevant parts: public class EventCache
{
private readonly SourceCache<ObservableEvent, int> _eventsCache = new(x => x.EventId);
private readonly SourceCache<LastAccess, int> _lastAccessCache = new(x => x.EventId);
private sealed record LastAccess(int EventId, DateTime Time)
{
public static LastAccess Now(int eventId) => new(eventId, DateTime.Now);
}
public EventCache()
{
_lastAccessCache
.ExpireAfter(_ => TimeSpan.FromDays(1), TimeSpan.FromHours(1))
.Subscribe(x => _eventsCache.RemoveKeys(x.Select(y => y.Key)));
}
public async Task<ObservableEvent> GetOrLoad(int eventId)
{
_lastAccessCache.AddOrUpdate(LastAccess.Now(eventId));
return GetFromCache(eventId) ?? await LoadFromDatabase(eventId);
}
private ObservableEvent GetFromCache(int eventId)
{
Optional<ObservableEvent> lookup = _eventsCache.Lookup(eventId);
return lookup.HasValue ? lookup.Value : null;
}
private async Task<ObservableEvent> LoadFromDatabase(int eventId)
{
ObservableEvent observableEvent;
...
return observableEvent;
}
} |
Beta Was this translation helpful? Give feedback.
-
Is it possible to create a sliding expiration for items in the source cache? I want to create a SourceCache that holds some data. On the first load I get the data from a database and put it inside the SourceCache. On following retrievals of the data I get it from the cache. I'd like to have a solution for a sliding cache expiration. Upon data retrieval from the cache I'd like to reset the expiry timer. I only want to remove items from the cache if nobody requires the data for a certain time.
Right now I use an absolute expiry, 1 day, with a polling interval of 1 hour. For the data retrieval from the cache I use the Lookup function.
I thought of having a LastAccessedTime property on my data item, but how to refresh it so that the ExpireAfter function gets it? Do I need to update the whole data item?
Beta Was this translation helpful? Give feedback.
All reactions