github.com/woocoos/entcache@v0.0.0-20231206055445-856f0148efa5/store.go (about)

     1  package entcache
     2  
     3  import (
     4  	"context"
     5  	"database/sql/driver"
     6  	"sync"
     7  	"time"
     8  )
     9  
    10  type (
    11  	Entry struct {
    12  		Columns []string
    13  		Values  [][]driver.Value
    14  	}
    15  
    16  	Key string
    17  )
    18  
    19  func NewEntryKey(typ string, id string) Key {
    20  	return Key(typ + ":" + id)
    21  }
    22  
    23  // ChangeSet is a set of keys that have changed, include update, delete, create.
    24  type ChangeSet struct {
    25  	sync.RWMutex
    26  	changes    map[Key]time.Time
    27  	refs       map[Key]time.Time
    28  	gcInterval time.Duration
    29  }
    30  
    31  func NewChangeSet(gcInterval time.Duration) *ChangeSet {
    32  	a := &ChangeSet{
    33  		changes:    make(map[Key]time.Time),
    34  		refs:       make(map[Key]time.Time),
    35  		gcInterval: gcInterval,
    36  	}
    37  	if a.gcInterval <= 0 {
    38  		a.gcInterval = defaultGCInterval
    39  	}
    40  	return a
    41  }
    42  
    43  func (a *ChangeSet) Start(ctx context.Context) error {
    44  	t := time.NewTicker(a.gcInterval)
    45  	defer t.Stop()
    46  	for {
    47  		select {
    48  		case <-ctx.Done():
    49  			return nil
    50  		case <-t.C:
    51  			a.gc()
    52  		}
    53  	}
    54  }
    55  
    56  func (a *ChangeSet) Stop(ctx context.Context) error {
    57  	return nil
    58  }
    59  
    60  func (a *ChangeSet) gc() {
    61  	a.Lock()
    62  	defer a.Unlock()
    63  	for k, v := range a.changes {
    64  		if time.Since(v) > a.gcInterval {
    65  			delete(a.changes, k)
    66  		}
    67  	}
    68  	for k, v := range a.refs {
    69  		if time.Since(v) > a.gcInterval {
    70  			delete(a.refs, k)
    71  		}
    72  	}
    73  }
    74  
    75  func (a *ChangeSet) Store(keys ...Key) {
    76  	a.Lock()
    77  	defer a.Unlock()
    78  	t := time.Now()
    79  	for _, key := range keys {
    80  		a.changes[key] = t
    81  	}
    82  }
    83  
    84  func (a *ChangeSet) Load(key Key) (time.Time, bool) {
    85  	a.RLock()
    86  	defer a.RUnlock()
    87  
    88  	v, ok := a.changes[key]
    89  	return v, ok
    90  }
    91  
    92  func (a *ChangeSet) Delete(key Key) {
    93  	a.Lock()
    94  	defer a.Unlock()
    95  
    96  	delete(a.changes, key)
    97  }
    98  
    99  func (a *ChangeSet) LoadRef(key Key) (time.Time, bool) {
   100  	a.RLock()
   101  	defer a.RUnlock()
   102  
   103  	v, ok := a.refs[key]
   104  	return v, ok
   105  }
   106  
   107  // LoadOrStoreRef returns the time when the key was last updated.
   108  func (a *ChangeSet) LoadOrStoreRef(key Key) (t time.Time, loaded bool) {
   109  	a.Lock()
   110  	defer a.Unlock()
   111  
   112  	t, loaded = a.refs[key]
   113  	a.refs[key] = time.Now()
   114  	return
   115  }
   116  
   117  func (a *ChangeSet) DeleteRef(key Key) {
   118  	a.Lock()
   119  	defer a.Unlock()
   120  
   121  	delete(a.refs, key)
   122  }