github.com/status-im/status-go@v1.1.0/services/wallet/balance/simple_cache.go (about) 1 package balance 2 3 import ( 4 "math" 5 "math/big" 6 ) 7 8 func NewSimpleCacher() Cacher { 9 return newCacherImpl(newSimpleCache()) 10 } 11 12 // implements cacheIface for plain map internal storage 13 type mapCache[K comparable, V any] struct { 14 cache map[K]V 15 } 16 17 func (c *mapCache[K, V]) get(key K) V { 18 return c.cache[key] 19 } 20 21 func (c *mapCache[K, V]) set(key K, value V) { 22 c.cache[key] = value 23 } 24 25 func (c *mapCache[K, V]) len() int { 26 return len(c.cache) 27 } 28 29 func (c *mapCache[K, V]) keys() []K { 30 keys := make([]K, 0, len(c.cache)) 31 for k := range c.cache { 32 keys = append(keys, k) 33 } 34 return keys 35 } 36 37 func (c *mapCache[K, V]) init() { 38 c.cache = make(map[K]V) 39 } 40 41 func (c *mapCache[K, V]) clear() { 42 c.cache = make(map[K]V) 43 } 44 45 // specializes generic cache 46 type simpleCache struct { 47 genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]] 48 } 49 50 func newSimpleCache() *simpleCache { 51 return &simpleCache{ 52 genericCache: genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]]{ 53 54 balances: make(addressChainMap[*mapCache[uint64, *big.Int]]), 55 nonces: make(addressChainMap[*mapCache[uint64, *int64]]), 56 nonceRangeCache: *newNonceRangeCache[*mapCache[int64, nonceRange]](), 57 }, 58 } 59 } 60 61 // Doesn't remove all entries, but keeps max and min to use on next iterations of transfer blocks searching 62 func (c *simpleCache) Clear() { 63 c.rw.Lock() 64 defer c.rw.Unlock() 65 66 for _, chainCache := range c.balances { 67 for _, cache := range chainCache { 68 if cache.len() == 0 { 69 continue 70 } 71 72 var maxBlock uint64 = 0 73 var minBlock uint64 = math.MaxUint64 74 for _, key := range cache.keys() { 75 if key > maxBlock { 76 maxBlock = key 77 } 78 if key < minBlock { 79 minBlock = key 80 } 81 } 82 maxBlockValue := cache.get(maxBlock) 83 minBlockValue := cache.get(maxBlock) 84 cache.clear() 85 86 if maxBlockValue != nil { 87 cache.set(maxBlock, maxBlockValue) 88 } 89 90 if minBlockValue != nil { 91 cache.set(minBlock, minBlockValue) 92 } 93 } 94 } 95 96 for _, chainCache := range c.nonces { 97 for _, cache := range chainCache { 98 if cache.len() == 0 { 99 continue 100 } 101 102 var maxBlock uint64 = 0 103 var minBlock uint64 = math.MaxUint64 104 for _, key := range cache.keys() { 105 if key > maxBlock { 106 maxBlock = key 107 } 108 if key < minBlock { 109 minBlock = key 110 } 111 } 112 maxBlockValue := cache.get(maxBlock) 113 minBlockValue := cache.get(maxBlock) 114 cache.clear() 115 116 if maxBlockValue != nil { 117 cache.set(maxBlock, maxBlockValue) 118 } 119 120 if minBlockValue != nil { 121 cache.set(minBlock, minBlockValue) 122 } 123 } 124 } 125 126 c.nonceRangeCache.clear() 127 }