Home
Insert
Update snippet 'Concurrent Memoization with Timeout'
Title
Description
This is variant of http://www.fssnip.net/sA that is having a time-out. You may want to use this if you e.g. cache a database query result or other mutable data source.
Source code
open System open System.Collections.Concurrent let memoize cacheTimeSeconds (caller:string) (f: ('a -> 'b)) = let cacheTimes = ConcurrentDictionary<string,DateTime>() let cache = ConcurrentDictionary<'a, 'b>() fun x -> match cacheTimes.TryGetValue caller with | true, time when time < DateTime.UtcNow.AddSeconds(-cacheTimeSeconds) -> cache.TryRemove(x) |> ignore | _ -> () cache.GetOrAdd(x, fun x -> cacheTimes.AddOrUpdate(caller, DateTime.UtcNow, fun _ _ ->DateTime.UtcNow)|> ignore f(x) ) let memoizeAsync cacheTimeSeconds (caller:string) (f: ('a -> Async<'b>)) = let cacheTimes = ConcurrentDictionary<string,DateTime>() let cache = ConcurrentDictionary<'a, System.Threading.Tasks.Task<'b>>() fun x -> match cacheTimes.TryGetValue caller with | true, time when time < DateTime.UtcNow.AddSeconds(-cacheTimeSeconds) -> cache.TryRemove(x) |> ignore | _ -> () cache.GetOrAdd(x, fun x -> cacheTimes.AddOrUpdate(caller, DateTime.UtcNow, fun _ _ ->DateTime.UtcNow)|> ignore f(x) |> Async.StartAsTask ) |> Async.AwaitTask (* Example test: let cacheTimeSeconds = 30. let myfun = memoize "myTest" cacheTimeSeconds (fun f -> Console.WriteLine("SideEffect"); f + 1) myfun 3 // "SideEffect" myfun 5 // "SideEffect" myfun 3 System.Threading.Thread.Sleep ((cacheTimeSeconds |> int) * 1000 + 100) myfun 3 // "SideEffect" myfun 3 *)
Tags
cache
memoization
memoize
timeout
cache
memoization
memoize
timeout
Author
Link
Reference NuGet packages
If your snippet has external dependencies, enter the names of NuGet packages to reference, separated by a comma (
#r
directives are not required).
Update