-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCache.fs
148 lines (128 loc) · 5 KB
/
Cache.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
namespace Sharpino
open Microsoft.Extensions.Logging
open Sharpino
open Sharpino.Core
open Sharpino.Definitions
open System.Runtime.CompilerServices
open Microsoft.Extensions.Logging.Abstractions
open System.Collections
open FSharp.Core
// open System.Runtime.Caching
open System
module Cache =
let logger: Microsoft.Extensions.Logging.ILogger ref = ref NullLogger.Instance
let setLogger (newLogger: Microsoft.Extensions.Logging.ILogger) =
logger := newLogger
let config =
try
Conf.config ()
with
| :? _ as ex ->
// if appSettings.json is missing
printf "appSettings.json file not found using default!!! %A\n" ex
Conf.defaultConf
type AggregateCache<'A, 'F when 'A :> Aggregate<'F>> private () =
// let cache = System.Runtime.Caching.MemoryCache.Default // will use this instead of dictionary later
let dic = Generic.Dictionary<EventId * AggregateId, Result<'A, string>>()
let queue = Generic.Queue<EventId * AggregateId>()
static let instance = AggregateCache<'A, 'F>()
static member Instance = instance
[<MethodImpl(MethodImplOptions.Synchronized)>]
member private this.TryAddToDictionary (arg, res) =
try
dic.Add(arg, res)
queue.Enqueue arg
if (queue.Count > config.CacheAggregateSize) then
let removed = queue.Dequeue()
dic.Remove removed |> ignore
()
with :? _ as e ->
logger.Value.LogError (sprintf "error: cache is doing something wrong. Resetting. %A\n" e)
dic.Clear()
queue.Clear()
()
member this.Memoize (f: unit -> Result<'A, string>) (arg: EventId * AggregateId) =
// sometimes you want to bypass cache for test
// f()
let (b, res) = dic.TryGetValue arg
if b then
res
else
this.Clean (arg |> snd)
let res = f()
this.TryAddToDictionary(arg, res)
res
member this.Memoize2 (x: Result<'A, string>) (arg: EventId * AggregateId) =
this.Clean (arg |> snd)
this.TryAddToDictionary(arg, x)
// sometimes you want to bypass cache for test
// ()
member this.Clean (aggregateId: AggregateId) =
let keys = dic.Keys
let keys' = keys |> List.ofSeq |> List.filter (fun (_, aggregateId') -> aggregateId = aggregateId')
keys' |> List.iter (fun key -> dic.Remove key |> ignore)
()
member this.LastEventId() =
dic.Keys
|> List.ofSeq
|> List.sort
|> List.tryLast
member this.LastEventId(aggregateId: Guid) =
dic.Keys
|> List.ofSeq
|> List.filter (fun (_, aggregateId') -> aggregateId = aggregateId')
|> List.map (fun (eventId, _) -> eventId)
|> List.sort
|> List.tryLast
member this.GetState (key: EventId * AggregateId) =
let (b, res) = dic.TryGetValue key
if b then
res
else
Error "state not found"
[<MethodImpl(MethodImplOptions.Synchronized)>]
member this.Clear() =
dic.Clear()
queue.Clear()
type StateCache2<'A> private () =
let mutable cachedValue: 'A option = None
let mutable eventId: EventId = 0
static let instance = StateCache2<'A>()
static member Instance = instance
[<MethodImpl(MethodImplOptions.Synchronized)>]
member this.TryCache (res: 'A, evId: EventId) =
cachedValue <- Some res
eventId <- evId
()
member this.GetState() =
match cachedValue with
| Some res -> Ok res
| None -> Error "state not found"
member this.Memoize (f: unit -> Result<'A, string>) (eventId: EventId)=
// f ()
match cachedValue with
| Some res -> Ok res
| _ ->
let res = f()
match res with
| Ok result ->
let _ = this.TryCache (result, eventId)
Ok result
| Error e ->
Error (e.ToString())
member this.GetEventIdAndState () =
// None
match cachedValue with
| Some res -> Some (eventId, res)
| None -> None
member this.Memoize2 (x: 'A) (eventId: EventId) =
// ()
this.TryCache (x, eventId)
member this.LastEventId() =
// 0
eventId
[<MethodImpl(MethodImplOptions.Synchronized)>]
member this.Invalidate() =
cachedValue <- None
eventId <- 0
()