Skip to content

Instantly share code, notes, and snippets.

@valerysntx
Last active December 28, 2016 06:57
Show Gist options
  • Save valerysntx/c54f03049d76b18fd04867dce1045287 to your computer and use it in GitHub Desktop.
Save valerysntx/c54f03049d76b18fd04867dce1045287 to your computer and use it in GitHub Desktop.
Cached Value Factory with Expiration
async static Task Main()
{
(await GetCachedContentAsync (new Uri ("http://foo"))).Dump();
//(await GetCachedContentAsync (new Uri ("http://foo"))).Dump();
}
static Task<string> GetContent (Uri uri) {
return Task.Delay (1000).ContinueWith (_ => "slow");
}
static Task<string> GetCachedContentAsync (Uri uri) {
return _getCachedContent (uri)();
}
static readonly Func<Uri, Func<Task<string>>> _getCachedContent =
Memoize<Uri, Func<Task<string>>> (
uri => WithExpiry (() => GetContent (uri), TimeSpan.FromSeconds(5)));
static Func<TKey, TValue> Memoize<TKey, TValue> (Func<TKey, TValue> getValueFunc)
{
var cache = new Dictionary<TKey, TValue>();
return (key =>
{
TValue result;
lock (cache)
{
if (cache.TryGetValue (key, out result)) return result;
return cache [key] = getValueFunc (key);
}
});
}
static Func<TResult> WithExpiry<TResult> (Func<TResult> payloadFunc, TimeSpan lifetime)
{
object locker = new object();
TResult payload = default(TResult);
DateTime expiry = DateTime.MinValue;
return () =>
{
lock (locker)
{
if (DateTime.UtcNow > expiry)
{
payload = payloadFunc();
expiry = DateTime.UtcNow + lifetime;
}
return payload;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment