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 }