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  }