github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/app/bcache/bcache.go (about)

     1  package bcache
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/songzhibin97/go-baseutils/base/bcomparator"
    10  	"github.com/songzhibin97/go-baseutils/base/bmap"
    11  	"github.com/songzhibin97/go-baseutils/base/options"
    12  	"github.com/songzhibin97/go-baseutils/structure/sets/zset"
    13  )
    14  
    15  const (
    16  	DefaultExpire time.Duration = 0
    17  	NoExpire      time.Duration = -1
    18  )
    19  
    20  var _ Cache[int, any] = (*BCache[int, any])(nil)
    21  
    22  type BCache[K comparable, V any] struct {
    23  	*bCache[K, V]
    24  }
    25  
    26  func New[K comparable, V any](comparator bcomparator.Comparator[K], opts ...options.Option[*Config[K, V]]) *BCache[K, V] {
    27  	ctx, cancel := context.WithCancel(context.Background())
    28  	c := &Config[K, V]{
    29  		defaultExpire: 0,
    30  		interval:      0,
    31  		capture: func(k K, v V) {
    32  			fmt.Printf("delete k:%v v:%v\n", k, v)
    33  		},
    34  		comparator: comparator,
    35  	}
    36  	for _, option := range opts {
    37  		option(c)
    38  	}
    39  	obj := &bCache[K, V]{
    40  		config:        c,
    41  		defaultExpire: c.defaultExpire,
    42  		capture:       c.capture,
    43  		cancel:        cancel,
    44  	}
    45  	if c.setSentinelFn == nil {
    46  		c.setSentinelFn = obj.deleteExpire
    47  	}
    48  	obj.member = bmap.NewUnsafeAnyBMap[K, Iterator[V]]()
    49  	obj.visit = zset.New[K](comparator)
    50  	go NewSentinel(ctx, c.interval, c.setSentinelFn).Start()
    51  	return &BCache[K, V]{obj}
    52  }
    53  
    54  func (c *BCache[K, V]) Set(k K, v V, d time.Duration) {
    55  	c.set(k, v, d)
    56  }
    57  
    58  func (c *BCache[K, V]) SetDefault(k K, v V) {
    59  	c.set(k, v, c.defaultExpire)
    60  }
    61  
    62  func (c *BCache[K, V]) SetNoExpire(k K, v V) {
    63  	c.set(k, v, NoExpire)
    64  }
    65  
    66  func (c *BCache[K, V]) SetIfAbsent(k K, v V, d time.Duration) bool {
    67  	return c.setIfAbsent(k, v, d)
    68  }
    69  
    70  func (c *BCache[K, V]) Replace(k K, v V, d time.Duration) bool {
    71  	return c.replace(k, v, d)
    72  }
    73  
    74  func (c *BCache[K, V]) Delete(k K) {
    75  	c.bCache.Delete(k)
    76  }
    77  
    78  func (c *BCache[K, V]) Get(k K) (V, bool) {
    79  	v, _, ok := c.get(k)
    80  	return v, ok
    81  }
    82  
    83  func (c *BCache[K, V]) GetWithExpire(k K) (V, time.Time, bool) {
    84  	v, t, ok := c.get(k)
    85  	return v, t, ok
    86  }
    87  
    88  func (c *BCache[K, V]) Count() int {
    89  	return c.count()
    90  }
    91  
    92  func (c *BCache[K, V]) Clear() {
    93  	c.clear()
    94  }
    95  
    96  func (c *BCache[K, V]) Load(data []byte) error {
    97  	return c.Unmarshal(data)
    98  }
    99  
   100  func (c *BCache[K, V]) Export() ([]byte, error) {
   101  	return c.Marshal()
   102  }
   103  
   104  type bCache[K comparable, V any] struct {
   105  	config *Config[K, V]
   106  
   107  	// defaultExpire 默认超时时间
   108  	defaultExpire time.Duration
   109  
   110  	sync.RWMutex // Protection member&visit
   111  
   112  	// member 维护map存储kv关系
   113  	member bmap.AnyBMap[K, Iterator[V]]
   114  
   115  	// visit 维护具有超时的key
   116  	visit *zset.Set[K]
   117  
   118  	// capture 捕获删除对象时间 会返回kv值用于用户自定义处理
   119  	capture func(k K, v V)
   120  
   121  	cancel context.CancelFunc
   122  
   123  	zero     V
   124  	zeroTime time.Time
   125  }
   126  
   127  func (c *bCache[K, V]) newIterator(v V, d time.Duration) Iterator[V] {
   128  	var expire int64
   129  	switch d {
   130  	case NoExpire:
   131  	case DefaultExpire:
   132  		if c.defaultExpire > 0 {
   133  			expire = time.Now().Add(c.defaultExpire).UnixNano()
   134  		}
   135  	default:
   136  		if d > 0 {
   137  			expire = time.Now().Add(d).UnixNano()
   138  		}
   139  		// 如果走到这里 默认是 NoExpire
   140  	}
   141  	return Iterator[V]{
   142  		Value:  v,
   143  		Expire: expire,
   144  	}
   145  }
   146  
   147  func (c *bCache[K, V]) set(k K, v V, d time.Duration) {
   148  
   149  	iter := c.newIterator(v, d)
   150  	c.Lock()
   151  	defer c.Unlock()
   152  
   153  	if iter.Expire != 0 {
   154  		c.visit.AddB(float64(iter.Expire), k)
   155  	}
   156  	c.member.Put(k, iter)
   157  }
   158  
   159  func (c *bCache[K, V]) setDeadline(k K, v V, d int64) {
   160  
   161  	if d != 0 {
   162  		c.visit.AddB(float64(d), k)
   163  	}
   164  	c.member.Put(k, Iterator[V]{
   165  		Value:  v,
   166  		Expire: d,
   167  	})
   168  }
   169  
   170  func (c *bCache[K, V]) setIfAbsent(k K, v V, d time.Duration) bool {
   171  	iter := c.newIterator(v, d)
   172  
   173  	c.Lock()
   174  	defer c.Unlock()
   175  
   176  	ok := c.member.PuTIfAbsent(k, iter)
   177  	if ok && iter.Expire != 0 {
   178  		c.visit.AddB(float64(iter.Expire), k)
   179  	}
   180  	return ok
   181  }
   182  
   183  func (c *bCache[K, V]) get(k K) (V, time.Time, bool) {
   184  	c.Lock()
   185  	defer c.Unlock()
   186  	v, ok := c.member.Get(k)
   187  	if !ok {
   188  		return c.zero, c.zeroTime, false
   189  	}
   190  	if v.expired() {
   191  		c.delete(k)
   192  		return c.zero, c.zeroTime, false
   193  	}
   194  	if !v.isVisit() {
   195  		return v.Value, c.zeroTime, true
   196  	}
   197  	return v.Value, time.Unix(0, v.Expire), true
   198  }
   199  
   200  func (c *bCache[K, V]) replace(k K, v V, d time.Duration) bool {
   201  	iter := c.newIterator(v, d)
   202  	c.Lock()
   203  	defer c.Unlock()
   204  	ov, ok := c.member.Get(k)
   205  	if !ok {
   206  		return false
   207  	}
   208  	if ov.expired() {
   209  		c.delete(k)
   210  		return false
   211  	}
   212  	c.member.Put(k, iter)
   213  	if iter.Expire != 0 {
   214  		c.visit.AddB(float64(iter.Expire), k)
   215  	}
   216  	return true
   217  }
   218  
   219  func (c *bCache[K, V]) Delete(k K) {
   220  	c.Lock()
   221  	defer c.Unlock()
   222  	v, ok := c.delete(k)
   223  	if ok && c.capture != nil {
   224  		c.capture(k, v)
   225  	}
   226  }
   227  
   228  func (c *bCache[K, V]) delete(k K) (V, bool) {
   229  	nv, ok := c.member.DeleteIfPresent(k)
   230  	if !ok {
   231  		return c.zero, false
   232  	}
   233  	c.visit.Remove(k)
   234  	return nv.Value, true
   235  }
   236  
   237  func (c *bCache[K, V]) deleteExpire() {
   238  	c.Lock()
   239  	defer c.Unlock()
   240  	nodes := c.visit.RemoveRangeByScore(0, float64(time.Now().UnixNano()))
   241  	for _, n := range nodes {
   242  		c.member.Delete(n.Value)
   243  	}
   244  }
   245  
   246  func (c *bCache[K, V]) count() int {
   247  	c.Lock()
   248  	defer c.Unlock()
   249  	return c.member.Size()
   250  }
   251  
   252  func (c *bCache[K, V]) clear() {
   253  	c.Lock()
   254  	defer c.Unlock()
   255  	c.member = bmap.NewUnsafeAnyBMap[K, Iterator[V]]()
   256  	c.visit = zset.New[K](c.config.comparator)
   257  }
   258  
   259  func (c *bCache[K, V]) Marshal() ([]byte, error) {
   260  	c.Lock()
   261  	defer c.Unlock()
   262  	return c.member.Marshal()
   263  }
   264  
   265  func (c *bCache[K, V]) Unmarshal(data []byte) error {
   266  	c.Lock()
   267  	defer c.Unlock()
   268  	mp := bmap.NewUnsafeAnyBMap[K, Iterator[V]]()
   269  	err := mp.Unmarshal(data)
   270  	if err != nil {
   271  		return err
   272  	}
   273  	mp.ForEach(func(k K, v Iterator[V]) {
   274  		if !v.expired() {
   275  			c.setDeadline(k, v.Value, v.Expire)
   276  		}
   277  	})
   278  	return nil
   279  }