Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace JMP.FSharpTools
- open System.Web
- open System.Web.Caching
- open System.Collections
- open System.Web.Configuration
- open Microsoft.FSharp.Reflection
- open System.Runtime.InteropServices
- //Modules are equivalent, machine code wise, to a static class in C#
- //So any methods defined in here should be callable as
- //TheOneCache.methodname
- //as long as the source file is using FsharpTools namespace
- module TheOneCache =
- type private CacheType = Web | Redis
- //The ICache interface, which can be implemented for IIS cache, Redis, etc
- type private ICache =
- abstract member Add: string -> 'T -> unit
- abstract member AddForTime: string -> 'T -> System.TimeSpan -> unit
- abstract member Get: string -> 'T option
- abstract member Exists: string -> bool
- abstract member Remove: string -> unit
- abstract member FlushAll: unit
- abstract member FlushKeysThatStartWith: string -> unit
- abstract member GetCountStartsWith: string -> int
- abstract member GetCacheType: CacheType
- //Implement the ICache interface as an IIS cache using an object expression
- let private WebCache =
- let GetHttpCacheEnum =
- HttpRuntime.Cache
- |> Seq.cast<DictionaryEntry>
- let FilterKeys keyPrefix =
- GetHttpCacheEnum
- |> Seq.filter(fun e -> e.Key.ToString().StartsWith(keyPrefix))
- { new ICache with
- member __.Add key value =
- HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null)
- member __.AddForTime key value duration =
- HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, duration, CacheItemPriority.NotRemovable, null)
- member __.Get<'T> key =
- match HttpRuntime.Cache.Get(key) with
- | null -> None
- | result -> Some (result :?> 'T)
- member __.Exists key =
- match HttpRuntime.Cache.Get(key) with
- | null -> false
- | _ -> true
- member __.Remove key =
- HttpRuntime.Cache.Remove(key) |> ignore
- member __.FlushAll =
- GetHttpCacheEnum
- |> Seq.iter(fun e -> HttpRuntime.Cache.Remove(e.Key.ToString()) |> ignore)
- member __.FlushKeysThatStartWith keyPrefix =
- FilterKeys keyPrefix
- |> Seq.iter(fun e -> HttpRuntime.Cache.Remove(e.Key.ToString()) |> ignore)
- member __.GetCountStartsWith keyPrefix =
- FilterKeys keyPrefix
- |> Seq.length
- member this.GetCacheType =
- CacheType.Web
- }
- //Our list of caches, for now just the IIS cache
- let private caches = [WebCache]
- //prints a union name as a string
- let private unionToString (x:'a) =
- match FSharpValue.GetUnionFields(x, typeof<'a>) with
- | case, _ -> case.Name
- //Like an enum
- type EntryType = Marklogic | SQL | Netsuite | Other with
- member this.ToString = unionToString this
- let StringToUnion<'T> (s:string) =
- match FSharpType.GetUnionCases (typeof<'T>) |> Array.filter (fun case -> case.Name = s) with
- |[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'T )
- |_ -> None
- type private EntryTypeRecord = { theType: EntryType;name: string; enabled: bool; mutable hits:int; mutable misses:int}
- let private CreateEntryTypeRecord entryType =
- {
- theType = entryType;
- name = entryType.ToString;
- enabled = System.Convert.ToBoolean(WebConfigurationManager.AppSettings.Get("Cache-"+entryType.ToString))
- hits = 0;
- misses = 0
- }
- let private allUnionCases<'T> =
- FSharpType.GetUnionCases(typeof<'T>)
- |> Array.map (fun case -> FSharpValue.MakeUnion(case,[||]):?>'T)
- let private EntryTypeMap =
- allUnionCases<EntryType>
- |> Seq.map( fun e -> e, CreateEntryTypeRecord e) |> Map.ofSeq
- //No need for objects, just functions
- let private ClearCounters entryType =
- EntryTypeMap.[entryType].hits <- 0
- EntryTypeMap.[entryType].misses <- 0
- let private ClearAllCounters =
- EntryTypeMap |> Seq.iter(fun r-> ClearCounters r.Value.theType)
- let Add (entryType:EntryType, key, value) =
- let entryRecord = EntryTypeMap.[entryType]
- match entryRecord.enabled with
- | true -> caches |> List.iter (fun c -> c.Add (entryRecord.name + key) value )
- | false -> ()
- let AddForTime(entryType:EntryType, key, value, duration) =
- let entryRecord = EntryTypeMap.[entryType]
- match entryRecord.enabled with
- | true -> caches |> List.iter (fun c-> c.AddForTime (entryRecord.name + key) value duration)
- | false -> ()
- let TryGetValue (entryType:EntryType, key,[<Out>] outValue :'T byref) =
- let entryRecord = EntryTypeMap.[entryType]
- match entryRecord.enabled with
- | true -> let result: 'T Option = caches |> List.tryPick (fun c -> c.Get (entryType.ToString + key))
- match result with
- | None -> entryRecord.misses <- entryRecord.misses + 1; outValue <- Unchecked.defaultof<'T>; false;
- | _ -> entryRecord.hits <- entryRecord.hits + 1; outValue <- result.Value; true;
- | false -> outValue <- null; false;
- let Remove (entryType:EntryType, key) =
- caches |> List.iter (fun c -> c.Remove (entryType.ToString + key ))
- let FlushAll =
- ClearAllCounters
- caches |> List.iter (fun c -> c.FlushAll)
- let FlushKeysThatStartWith keyPrefix =
- caches |> List.iter (fun c -> c.FlushKeysThatStartWith keyPrefix)
- let FlushEntryType (entryType:EntryType) =
- ClearCounters entryType
- FlushKeysThatStartWith entryType.ToString
- let GetHits entryType =
- EntryTypeMap.[entryType].hits
- let GetMisses entryType =
- EntryTypeMap.[entryType].misses
- let GetCount (entryType : EntryType) =
- caches |> List.map(fun c-> c.GetCountStartsWith entryType.ToString) |> List.reduce (+)
- let AddSession (entryType:EntryType, key, value) =
- match HttpContext.Current.Session with
- | null -> ()
- | _ -> HttpContext.Current.Session.Add(entryType.ToString+key, value)
- let AddRequest (entryType:EntryType, key, value) =
- HttpContext.Current.Items.Add(entryType.ToString+key, value)
- let TryGetFromSession (entryType:EntryType, key, [<Out>] outValue: 'T byref) =
- match HttpContext.Current.Session with
- | null -> outValue <- Unchecked.defaultof<'T>;false
- | _ -> match HttpContext.Current.Session.[entryType.ToString + key] with
- | null -> outValue <- Unchecked.defaultof<'T>; false
- | result -> outValue <- result :?> 'T; true
- let TryGetFromRequest (entryType:EntryType, key,[<Out>] outValue: 'T byref) =
- match HttpContext.Current.Items.[entryType.ToString + key] with
- | null -> outValue <- Unchecked.defaultof<'T>; false
- | result -> outValue <- result :?> 'T ; true
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement