github.com/oam-dev/kubevela@v1.9.11/pkg/utils/cache.go (about) 1 /* 2 Copyright 2021 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils 18 19 import ( 20 "context" 21 "sync" 22 "time" 23 ) 24 25 // memoryCache memory cache, support time expired 26 type memoryCache struct { 27 data interface{} 28 cacheDuration time.Duration 29 startTime time.Time 30 } 31 32 // NewMemoryCache new memory cache instance 33 func newMemoryCache(data interface{}, cacheDuration time.Duration) *memoryCache { 34 mc := &memoryCache{data: data, cacheDuration: cacheDuration, startTime: time.Now()} 35 return mc 36 } 37 38 // IsExpired whether the cache data expires 39 func (m *memoryCache) IsExpired() bool { 40 if m.cacheDuration <= 0 { 41 return false 42 } 43 return time.Now().After(m.startTime.Add(m.cacheDuration)) 44 } 45 46 // GetData get cache data 47 func (m *memoryCache) GetData() interface{} { 48 return m.data 49 } 50 51 // MemoryCacheStore a sample memory cache instance, if data set cache duration, will auto clear after timeout. 52 // But, Expired cleanup is not necessarily accurate, it has a 3-second window. 53 type MemoryCacheStore struct { 54 store sync.Map 55 } 56 57 // NewMemoryCacheStore memory cache store 58 func NewMemoryCacheStore(ctx context.Context) *MemoryCacheStore { 59 mcs := &MemoryCacheStore{ 60 store: sync.Map{}, 61 } 62 go mcs.run(ctx) 63 return mcs 64 } 65 66 func (m *MemoryCacheStore) run(ctx context.Context) { 67 ticker := time.NewTicker(time.Second * 3) 68 defer ticker.Stop() 69 for { 70 select { 71 case <-ctx.Done(): 72 return 73 case <-ticker.C: 74 m.store.Range(func(key, value interface{}) bool { 75 if value.(*memoryCache).IsExpired() { 76 m.store.Delete(key) 77 } 78 return true 79 }) 80 } 81 } 82 } 83 84 // Put cache data, if cacheDuration>0, store will clear data after timeout. 85 func (m *MemoryCacheStore) Put(key, value interface{}, cacheDuration time.Duration) { 86 mc := newMemoryCache(value, cacheDuration) 87 m.store.Store(key, mc) 88 } 89 90 // Delete cache data from store 91 func (m *MemoryCacheStore) Delete(key interface{}) { 92 m.store.Delete(key) 93 } 94 95 // Get cache data from store, if not exist or timeout, will return nil 96 func (m *MemoryCacheStore) Get(key interface{}) (value interface{}) { 97 mc, ok := m.store.Load(key) 98 if ok && !mc.(*memoryCache).IsExpired() { 99 return mc.(*memoryCache).GetData() 100 } 101 return nil 102 }