namespace MyWebLog open Microsoft.AspNetCore.Http /// Helper functions for caches module Cache = /// Create the cache key for the web log for the current request let makeKey (ctx : HttpContext) = ctx.Request.Host.ToUriComponent () open System.Collections.Concurrent /// /// In-memory cache of web log details /// /// This is filled by the middleware via the first request for each host, and can be updated via the web log /// settings update page module WebLogCache = /// The cache of web log details let private _cache = ConcurrentDictionary () /// Does a host exist in the cache? let exists ctx = _cache.ContainsKey (Cache.makeKey ctx) /// Get the web log for the current request let get ctx = _cache[Cache.makeKey ctx] /// Cache the web log for a particular host let set ctx webLog = _cache[Cache.makeKey ctx] <- webLog open Microsoft.Extensions.DependencyInjection open RethinkDb.Driver.Net /// 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 () /// 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 let update ctx = task { let webLog = WebLogCache.get ctx let conn = ctx.RequestServices.GetRequiredService () let! pages = Data.Page.findListed webLog.id conn _cache[Cache.makeKey ctx] <- pages |> List.map (DisplayPage.fromPage webLog) |> Array.ofList } /// Cache of all categories, indexed by web log module CategoryCache = open MyWebLog.ViewModels /// The cache itself let private _cache = ConcurrentDictionary () /// Get the categories for the web log for this request let get ctx = _cache[Cache.makeKey ctx] /// Update the cache with fresh data let update ctx = backgroundTask { let webLog = WebLogCache.get ctx let conn = ctx.RequestServices.GetRequiredService () let! cats = Data.Category.findAllForView webLog.id conn _cache[Cache.makeKey ctx] <- cats } /// Cache for parsed templates module TemplateCache = open DotLiquid open System.IO /// Cache of parsed templates let private _cache = ConcurrentDictionary () /// Get a template for the given theme and template nate let get (theme : string) (templateName : string) = task { 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] }