Last active
December 28, 2016 06:57
-
-
Save valerysntx/c54f03049d76b18fd04867dce1045287 to your computer and use it in GitHub Desktop.
Cached Value Factory with Expiration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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