Last active
January 15, 2022 08:56
-
-
Save JordanMarr/631806b2d24984c50ec22468db6fcfe2 to your computer and use it in GitHub Desktop.
F# Cache utility for ASP.NET
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
module Cache | |
open System | |
open Microsoft.AspNetCore.Http | |
open Microsoft.Extensions.Caching.Memory | |
type CacheExpiration = | |
| Absolute of DateTimeOffset | |
| AbsoluteRelativeToNow of TimeSpan | |
| Sliding of TimeSpan | |
/// Caches the results of an async function for a given key / expiration. | |
let cacheAsync<'Payload> (ctx: HttpContext) (key: string) (expiration: CacheExpiration) fn = | |
let cache = ctx.GetService<IMemoryCache>() | |
cache.GetOrCreateAsync<'Payload>(key, fun entry -> | |
task { | |
printfn $"'{key}' not found in cache." | |
match expiration with | |
| Absolute dt -> entry.AbsoluteExpiration <- Nullable dt | |
| AbsoluteRelativeToNow ts -> entry.AbsoluteExpirationRelativeToNow <- Nullable ts | |
| Sliding ts -> entry.SlidingExpiration <- Nullable ts | |
let! payload = fn |> Async.StartAsTask | |
let expirationDescription = | |
match expiration with | |
| Absolute dt -> $"{dt - DateTimeOffset.Now}" | |
| AbsoluteRelativeToNow ts -> $"{ts}" | |
| Sliding ts -> $"{ts} after last use" | |
printfn $"'{key}' added to cache for {expirationDescription}." | |
return payload | |
} | |
) | |
|> Async.AwaitTask | |
/// Clears the results from cache. | |
let invalidateCache (ctx: HttpContext) (key: string) = | |
let cache = ctx.GetService<IMemoryCache>() | |
cache.Remove(key) |
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
module Handlers | |
open Microsoft.AspNetCore.Http | |
let getWidgets (ctx: HttpContext) (projectId: int) = | |
async { | |
let! widgets = Widgets.IO.getWidgets projectId | |
return widgets | |
} | |
// USAGE: | |
let getWidgetsCached (ctx: HttpContext) (projectId: int) = | |
async { | |
let! widgets = | |
let key = $"widgets_%i{projectId}" | |
let expiration = Cache.AbsoluteRelativeToNow (TimeSpan.FromMinutes 15.) | |
Cache.cacheAsync ctx key expiration (Widgets.IO.getWidgets projectId) | |
return widgets | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment