Advertisement
jackmott

My First F#

Feb 2nd, 2016
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 7.97 KB | None | 0 0
  1. namespace JMP.FSharpTools
  2. open System.Web
  3. open System.Web.Caching
  4. open System.Collections
  5. open System.Web.Configuration
  6. open Microsoft.FSharp.Reflection
  7. open System.Runtime.InteropServices
  8.  
  9. //Modules are equivalent, machine code wise, to a static class in C#
  10. //So any methods defined in here should be callable as
  11. //TheOneCache.methodname
  12. //as long as the source file is using FsharpTools namespace
  13. module TheOneCache =
  14.  
  15.     type private CacheType = Web | Redis
  16.  
  17.     //The ICache interface, which can be implemented for IIS cache, Redis, etc
  18.     type private ICache =
  19.         abstract member Add: string -> 'T -> unit
  20.        abstract member AddForTime: string -> 'T -> System.TimeSpan -> unit
  21.         abstract member Get: string -> 'T option
  22.        abstract member Exists: string -> bool
  23.        abstract member Remove: string -> unit
  24.        abstract member FlushAll: unit
  25.        abstract member FlushKeysThatStartWith: string -> unit                      
  26.        abstract member GetCountStartsWith: string -> int
  27.        abstract member GetCacheType: CacheType
  28.  
  29.    //Implement the ICache interface as an IIS cache using an object expression
  30.    let private WebCache =
  31.        let GetHttpCacheEnum =
  32.                HttpRuntime.Cache
  33.                |> Seq.cast<DictionaryEntry>
  34.            
  35.        let FilterKeys keyPrefix =
  36.                GetHttpCacheEnum
  37.                |> Seq.filter(fun e -> e.Key.ToString().StartsWith(keyPrefix))
  38.  
  39.        {   new ICache with
  40.            
  41.            member __.Add key value =
  42.                HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null)                            
  43.            
  44.            member __.AddForTime key value duration =
  45.                HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, duration, CacheItemPriority.NotRemovable, null)                            
  46.            
  47.            member __.Get<'T> key =
  48.                  match HttpRuntime.Cache.Get(key) with
  49.                  | null -> None
  50.                  | result -> Some (result :?> 'T)
  51.  
  52.            member __.Exists key =
  53.                match HttpRuntime.Cache.Get(key) with
  54.                | null -> false
  55.                | _ -> true
  56.            
  57.            member __.Remove key =
  58.                HttpRuntime.Cache.Remove(key)  |> ignore        
  59.                      
  60.            member __.FlushAll =                                
  61.                GetHttpCacheEnum
  62.                |> Seq.iter(fun e -> HttpRuntime.Cache.Remove(e.Key.ToString()) |> ignore)
  63.                        
  64.            member __.FlushKeysThatStartWith keyPrefix =
  65.                FilterKeys keyPrefix
  66.                |> Seq.iter(fun e -> HttpRuntime.Cache.Remove(e.Key.ToString()) |> ignore)                                                            
  67.                                                                              
  68.            member __.GetCountStartsWith keyPrefix =
  69.                FilterKeys keyPrefix                
  70.                |> Seq.length                
  71.  
  72.            member this.GetCacheType =
  73.                CacheType.Web
  74.  
  75.          
  76.        }
  77.  
  78.    
  79.  
  80.    //Our list of caches, for now just the IIS cache
  81.    let private caches = [WebCache]      
  82.    
  83.    //prints a union name as a string
  84.    let private unionToString (x:'a) =
  85.         match FSharpValue.GetUnionFields(x, typeof<'a>) with
  86.        | case, _ -> case.Name
  87.  
  88.    
  89.    //Like an enum
  90.    type EntryType = Marklogic | SQL | Netsuite | Other with
  91.        member this.ToString = unionToString this
  92.  
  93.    let StringToUnion<'T> (s:string) =
  94.         match FSharpType.GetUnionCases (typeof<'T>) |> Array.filter (fun case -> case.Name = s) with
  95.        |[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'T )
  96.         |_ -> None
  97.  
  98.     type private EntryTypeRecord = { theType: EntryType;name: string; enabled: bool; mutable hits:int; mutable misses:int}
  99.  
  100.     let private CreateEntryTypeRecord entryType =
  101.         {
  102.             theType = entryType;
  103.             name = entryType.ToString;
  104.             enabled = System.Convert.ToBoolean(WebConfigurationManager.AppSettings.Get("Cache-"+entryType.ToString))
  105.             hits = 0;
  106.             misses = 0
  107.         }
  108.            
  109.     let private allUnionCases<'T> =
  110.        FSharpType.GetUnionCases(typeof<'T>)
  111.         |> Array.map (fun case -> FSharpValue.MakeUnion(case,[||]):?>'T)
  112.  
  113.    let private EntryTypeMap =
  114.        allUnionCases<EntryType>
  115.        |> Seq.map( fun e -> e, CreateEntryTypeRecord e) |> Map.ofSeq
  116.  
  117.          
  118.    //No need for objects, just functions
  119.    let private ClearCounters entryType =
  120.        EntryTypeMap.[entryType].hits <- 0
  121.        EntryTypeMap.[entryType].misses <- 0
  122.  
  123.    let private ClearAllCounters =
  124.        EntryTypeMap |> Seq.iter(fun r-> ClearCounters r.Value.theType)
  125.        
  126.        
  127.    let Add (entryType:EntryType, key, value) =
  128.        let entryRecord = EntryTypeMap.[entryType]
  129.        match entryRecord.enabled with
  130.        | true -> caches |> List.iter (fun c -> c.Add (entryRecord.name + key) value )
  131.        | false -> ()          
  132.  
  133.    let AddForTime(entryType:EntryType, key, value, duration) =
  134.        let entryRecord = EntryTypeMap.[entryType]
  135.        match entryRecord.enabled with
  136.        | true ->  caches |> List.iter (fun c-> c.AddForTime (entryRecord.name + key) value duration)
  137.        | false -> ()  
  138.  
  139.    let TryGetValue (entryType:EntryType, key,[<Out>]  outValue :'T byref) =
  140.         let entryRecord = EntryTypeMap.[entryType]
  141.         match entryRecord.enabled with        
  142.         | true -> let result: 'T Option = caches |> List.tryPick (fun c -> c.Get (entryType.ToString + key))  
  143.                  match result with                  
  144.                  | None ->  entryRecord.misses <- entryRecord.misses + 1;  outValue <- Unchecked.defaultof<'T>; false;
  145.                   | _ ->  entryRecord.hits <- entryRecord.hits + 1; outValue <- result.Value; true;
  146.         | false -> outValue <- null; false;  
  147.  
  148.     let Remove (entryType:EntryType, key) =
  149.         caches |> List.iter (fun c -> c.Remove (entryType.ToString + key ))  
  150.  
  151.     let FlushAll =
  152.         ClearAllCounters
  153.         caches |> List.iter (fun c -> c.FlushAll)      
  154.  
  155.     let FlushKeysThatStartWith keyPrefix =
  156.         caches |> List.iter (fun c -> c.FlushKeysThatStartWith keyPrefix)
  157.  
  158.     let FlushEntryType (entryType:EntryType) =
  159.         ClearCounters entryType
  160.         FlushKeysThatStartWith entryType.ToString
  161.  
  162.     let GetHits entryType =
  163.         EntryTypeMap.[entryType].hits
  164.  
  165.     let GetMisses entryType =
  166.         EntryTypeMap.[entryType].misses
  167.  
  168.     let GetCount (entryType : EntryType) =
  169.         caches |> List.map(fun c-> c.GetCountStartsWith entryType.ToString) |> List.reduce (+)
  170.  
  171.     let AddSession (entryType:EntryType, key, value) =
  172.         match HttpContext.Current.Session with
  173.             | null -> ()
  174.             | _    -> HttpContext.Current.Session.Add(entryType.ToString+key, value)
  175.  
  176.     let AddRequest (entryType:EntryType, key, value) =
  177.         HttpContext.Current.Items.Add(entryType.ToString+key, value)
  178.  
  179.     let TryGetFromSession (entryType:EntryType, key, [<Out>]  outValue: 'T byref) =
  180.        match HttpContext.Current.Session with
  181.            | null -> outValue <- Unchecked.defaultof<'T>;false
  182.             | _    -> match HttpContext.Current.Session.[entryType.ToString + key] with
  183.                       | null -> outValue <- Unchecked.defaultof<'T>; false
  184.                      | result -> outValue <- result :?> 'T; true
  185.  
  186.     let TryGetFromRequest (entryType:EntryType, key,[<Out>]  outValue: 'T byref) =
  187.        match HttpContext.Current.Items.[entryType.ToString + key] with
  188.                 | null -> outValue <- Unchecked.defaultof<'T>; false
  189.                  | result -> outValue <- result :?> 'T ; true
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement