Skip to content

Instantly share code, notes, and snippets.

@aaronmu
Last active October 20, 2021 14:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronmu/2ca737e35dd022ac0eaf93a0b599a432 to your computer and use it in GitHub Desktop.
Save aaronmu/2ca737e35dd022ac0eaf93a0b599a432 to your computer and use it in GitHub Desktop.
type Timed<'T> =
{ Timestamp: DateTimeOffset
Value: 'T }
type Clock = unit -> DateTimeOffset
let Timed (c: Clock) v =
{ Timestamp = c ()
Value = v }
let memoizeAsyncFn (clock: Clock) (expiresAt: DateTimeOffset) fn =
let d = ConcurrentDictionary ()
let tryFind k =
match d.TryGetValue k with
| true, timedValue ->
if timedValue.Timestamp >= expiresAt then
None
else
Some timedValue.Value
| false, _ -> None
let addOrUpdate k v =
let v = Timed clock v
let setter = Func<_, _,_>(fun _ _ -> v)
d.AddOrUpdate (k, v, setter)
async {
while true do
for kvp in d do
if kvp.Value.Timestamp >= expiresAt then
let _ = d.Remove kvp.Key
()
else
()
do! Async.Sleep 60000
} |> Async.Start
fun x ->
match tryFind x with
| Some v -> async { return v }
| None ->
async {
let! v = fn x
let _ = addOrUpdate x v
return v
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment