2022-04-18 22:06:17 +00:00
|
|
|
namespace MyWebLog
|
|
|
|
|
|
|
|
open Microsoft.AspNetCore.Http
|
|
|
|
|
|
|
|
/// Helper functions for caches
|
|
|
|
module Cache =
|
|
|
|
|
|
|
|
/// Create the cache key for the web log for the current request
|
2022-05-22 02:55:13 +00:00
|
|
|
let makeKey (ctx : HttpContext) = (ctx.Items["webLog"] :?> WebLog).urlBase
|
2022-04-18 22:06:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
open System.Collections.Concurrent
|
2022-05-22 02:55:13 +00:00
|
|
|
open Microsoft.Extensions.DependencyInjection
|
|
|
|
open RethinkDb.Driver.Net
|
2022-04-18 22:06:17 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// In-memory cache of web log details
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>This is filled by the middleware via the first request for each host, and can be updated via the web log
|
|
|
|
/// settings update page</remarks>
|
|
|
|
module WebLogCache =
|
2022-05-22 02:55:13 +00:00
|
|
|
|
|
|
|
/// Create the full path of the request
|
|
|
|
let private fullPath (ctx : HttpContext) =
|
|
|
|
$"{ctx.Request.Scheme}://{ctx.Request.Host.Value}{ctx.Request.Path.Value}"
|
|
|
|
|
2022-04-18 22:06:17 +00:00
|
|
|
/// The cache of web log details
|
2022-05-22 02:55:13 +00:00
|
|
|
let mutable private _cache : WebLog list = []
|
2022-04-18 22:06:17 +00:00
|
|
|
|
|
|
|
/// Does a host exist in the cache?
|
2022-05-22 02:55:13 +00:00
|
|
|
let exists ctx =
|
|
|
|
let path = fullPath ctx
|
|
|
|
_cache |> List.exists (fun wl -> path.StartsWith wl.urlBase)
|
2022-04-18 22:06:17 +00:00
|
|
|
|
|
|
|
/// Get the web log for the current request
|
2022-05-22 02:55:13 +00:00
|
|
|
let get ctx =
|
|
|
|
let path = fullPath ctx
|
|
|
|
_cache |> List.find (fun wl -> path.StartsWith wl.urlBase)
|
2022-04-18 22:06:17 +00:00
|
|
|
|
|
|
|
/// Cache the web log for a particular host
|
2022-05-22 02:55:13 +00:00
|
|
|
let set webLog =
|
|
|
|
_cache <- webLog :: (_cache |> List.filter (fun wl -> wl.id <> webLog.id))
|
|
|
|
|
|
|
|
/// Fill the web log cache from the database
|
|
|
|
let fill conn = backgroundTask {
|
|
|
|
let! webLogs = Data.WebLog.all conn
|
|
|
|
_cache <- webLogs
|
|
|
|
}
|
2022-04-18 22:06:17 +00:00
|
|
|
|
2022-04-28 00:01:33 +00:00
|
|
|
|
2022-04-18 22:06:17 +00:00
|
|
|
/// A cache of page information needed to display the page list in templates
|
|
|
|
module PageListCache =
|
|
|
|
|
|
|
|
open MyWebLog.ViewModels
|
|
|
|
|
|
|
|
/// Cache of displayed pages
|
|
|
|
let private _cache = ConcurrentDictionary<string, DisplayPage[]> ()
|
|
|
|
|
2022-05-22 02:55:13 +00:00
|
|
|
/// Are there pages cached for this web log?
|
|
|
|
let exists ctx = _cache.ContainsKey (Cache.makeKey ctx)
|
|
|
|
|
2022-04-18 22:06:17 +00:00
|
|
|
/// Get the pages for the web log for this request
|
|
|
|
let get ctx = _cache[Cache.makeKey ctx]
|
|
|
|
|
|
|
|
/// Update the pages for the current web log
|
2022-05-22 02:55:13 +00:00
|
|
|
let update (ctx : HttpContext) = backgroundTask {
|
|
|
|
let webLog = ctx.Items["webLog"] :?> WebLog
|
2022-04-18 22:06:17 +00:00
|
|
|
let conn = ctx.RequestServices.GetRequiredService<IConnection> ()
|
|
|
|
let! pages = Data.Page.findListed webLog.id conn
|
|
|
|
_cache[Cache.makeKey ctx] <- pages |> List.map (DisplayPage.fromPage webLog) |> Array.ofList
|
|
|
|
}
|
|
|
|
|
2022-04-27 02:24:17 +00:00
|
|
|
|
|
|
|
/// Cache of all categories, indexed by web log
|
|
|
|
module CategoryCache =
|
|
|
|
|
|
|
|
open MyWebLog.ViewModels
|
|
|
|
|
|
|
|
/// The cache itself
|
|
|
|
let private _cache = ConcurrentDictionary<string, DisplayCategory[]> ()
|
|
|
|
|
2022-05-22 02:55:13 +00:00
|
|
|
/// Are there categories cached for this web log?
|
|
|
|
let exists ctx = _cache.ContainsKey (Cache.makeKey ctx)
|
|
|
|
|
2022-04-27 02:24:17 +00:00
|
|
|
/// Get the categories for the web log for this request
|
|
|
|
let get ctx = _cache[Cache.makeKey ctx]
|
|
|
|
|
2022-04-28 00:01:33 +00:00
|
|
|
/// Update the cache with fresh data
|
2022-05-22 02:55:13 +00:00
|
|
|
let update (ctx : HttpContext) = backgroundTask {
|
|
|
|
let webLog = ctx.Items["webLog"] :?> WebLog
|
2022-04-28 00:01:33 +00:00
|
|
|
let conn = ctx.RequestServices.GetRequiredService<IConnection> ()
|
|
|
|
let! cats = Data.Category.findAllForView webLog.id conn
|
|
|
|
_cache[Cache.makeKey ctx] <- cats
|
|
|
|
}
|
2022-04-27 02:24:17 +00:00
|
|
|
|
|
|
|
|
2022-04-18 22:06:17 +00:00
|
|
|
/// Cache for parsed templates
|
|
|
|
module TemplateCache =
|
|
|
|
|
|
|
|
open DotLiquid
|
|
|
|
open System.IO
|
|
|
|
|
|
|
|
/// Cache of parsed templates
|
|
|
|
let private _cache = ConcurrentDictionary<string, Template> ()
|
|
|
|
|
|
|
|
/// Get a template for the given theme and template nate
|
2022-05-22 02:55:13 +00:00
|
|
|
let get (theme : string) (templateName : string) = backgroundTask {
|
2022-04-18 22:06:17 +00:00
|
|
|
let templatePath = $"themes/{theme}/{templateName}"
|
|
|
|
match _cache.ContainsKey templatePath with
|
|
|
|
| true -> ()
|
|
|
|
| false ->
|
|
|
|
let! file = File.ReadAllTextAsync $"{templatePath}.liquid"
|
|
|
|
_cache[templatePath] <- Template.Parse (file, SyntaxCompatibility.DotLiquid22)
|
|
|
|
return _cache[templatePath]
|
|
|
|
}
|
|
|
|
|