@@ -3,6 +3,7 @@ package storage
33import (
44 "container/list"
55 "context"
6+ "math"
67 "sync"
78 "time"
89
@@ -12,18 +13,18 @@ import (
1213
1314type LFUCache struct {
1415 mtx sync.RWMutex
15- min int
16+ min uint
1617 capacityMB float64
1718 sizeMB float64
1819 lookupTimeout time.Duration
19- lists map [int ]* FrequencyList
20+ lists map [uint ]* FrequencyList
2021 cache map [string ]* list.Element
2122 staleDuration int64
2223}
2324
2425type FrequencyList struct {
2526 lruCache * list.List
26- counter int
27+ counter uint
2728}
2829
2930type LfuNode struct {
@@ -43,7 +44,7 @@ func NewLFUCache(maxSizeMB float64, staleInSeconds int64) *LFUCache {
4344 capacityMB : maxSizeMB ,
4445 lookupTimeout : lookupTimeout ,
4546 sizeMB : 0 ,
46- lists : make (map [int ]* FrequencyList ),
47+ lists : make (map [uint ]* FrequencyList ),
4748 cache : make (map [string ]* list.Element ),
4849 staleDuration : staleInSeconds ,
4950 }
@@ -53,7 +54,7 @@ func (lfu *LFUCache) Store(ctx context.Context, key string, value *model.Respons
5354 lfu .mtx .Lock ()
5455 defer lfu .mtx .Unlock ()
5556
56- bodySizeMB := lfu . getSize (* value )
57+ bodySizeMB := getSize (* value )
5758
5859 if bodySizeMB > lfu .capacityMB {
5960 log .Ctx (ctx ).Warn ().Msg ("The size of the body is bigger than the configured LRU cache maxSize. The body will not be stored." )
@@ -64,7 +65,7 @@ func (lfu *LFUCache) Store(ctx context.Context, key string, value *model.Respons
6465 val , found := lfu .cache [key ]
6566
6667 if found {
67- bodySizeMB -= lfu . getSize (* val .Value .(* LfuNode ).value )
68+ bodySizeMB -= getSize (* val .Value .(* LfuNode ).value )
6869 node := val .Value .(* LfuNode )
6970 node .value = value
7071 node .timeStamp = time .Now ().Unix ()
@@ -74,17 +75,7 @@ func (lfu *LFUCache) Store(ctx context.Context, key string, value *model.Respons
7475 lfu .sizeMB += bodySizeMB
7576
7677 for lfu .sizeMB > lfu .capacityMB {
77- freqList := lfu .lists [lfu .min ].lruCache
78- ejectedNode := freqList .Back ()
79- freqList .Remove (ejectedNode )
80-
81- if freqList .Len () == 0 {
82- delete (lfu .lists , lfu .min )
83- }
84-
85- delete (lfu .cache , ejectedNode .Value .(* LfuNode ).key )
86-
87- lfu .sizeMB -= lfu .getSize (* ejectedNode .Value .(* LfuNode ).value )
78+ lfu .ejectNode ()
8879 }
8980
9081 if ! found {
@@ -116,11 +107,7 @@ func (lfu *LFUCache) LookUp(ctx context.Context, key string) (*model.Response, e
116107 lfu .update (val )
117108 node := val .Value .(* LfuNode )
118109 response := node .value
119- if (time .Now ().Unix () - node .timeStamp ) >= lfu .staleDuration {
120- response .StaleValue = model .StaleValue
121- } else {
122- response .StaleValue = model .FreshValue
123- }
110+ response .StaleValue = getStaleStatus (node .timeStamp , lfu .staleDuration )
124111
125112 proc <- response
126113
@@ -159,7 +146,7 @@ func (lfu *LFUCache) update(node *list.Element) {
159146 lfu .moveNode (node .Value .(* LfuNode ), count + 1 )
160147}
161148
162- func (lfu * LFUCache ) moveNode (node * LfuNode , count int ) * list.Element {
149+ func (lfu * LFUCache ) moveNode (node * LfuNode , count uint ) * list.Element {
163150 if _ , found := lfu .lists [count ]; ! found {
164151 lfu .lists [count ] = & FrequencyList {
165152 lruCache : list .New (),
@@ -174,9 +161,33 @@ func (lfu *LFUCache) moveNode(node *LfuNode, count int) *list.Element {
174161 return returnedLfuNode
175162}
176163
177- func (lfu * LFUCache ) getSize (value model.Response ) float64 {
178- sizeBytes := len (value .Body )
179- sizeMB := float64 (sizeBytes ) / (1024 * 1024 )
164+ func (lfu * LFUCache ) ejectNode () {
165+ freqList := lfu .lists [lfu .min ].lruCache
166+ ejectedNode := freqList .Back ()
167+ freqList .Remove (ejectedNode )
168+
169+ if freqList .Len () == 0 {
170+ delete (lfu .lists , lfu .min )
171+ lfu .min = lfu .findNextMin ()
172+ }
173+
174+ delete (lfu .cache , ejectedNode .Value .(* LfuNode ).key )
175+
176+ lfu .sizeMB -= getSize (* ejectedNode .Value .(* LfuNode ).value )
177+ }
178+
179+ func (lfu * LFUCache ) findNextMin () uint {
180+ if _ , found := lfu .lists [lfu .min + 1 ]; found {
181+ return lfu .min + 1
182+ }
183+
184+ var newMin uint = math .MaxUint
185+
186+ for k := range lfu .lists {
187+ if k < newMin {
188+ newMin = k
189+ }
190+ }
180191
181- return sizeMB
192+ return newMin
182193}
0 commit comments