github.com/rosedblabs/rosedb/v2@v2.3.7-0.20240423093736-a89ea823e5b9/watch.go (about) 1 package rosedb 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type WatchActionType = byte 9 10 const ( 11 WatchActionPut WatchActionType = iota 12 WatchActionDelete 13 ) 14 15 // Event is the event that occurs when the database is modified. 16 // It is used to synchronize the watch of the database. 17 type Event struct { 18 Action WatchActionType 19 Key []byte 20 Value []byte 21 BatchId uint64 22 } 23 24 // Watcher temporarily stores event information, 25 // as it is generated until it is synchronized to DB's watch. 26 // 27 // If the event is overflow, It will remove the oldest data, 28 // even if event hasn't been read yet. 29 type Watcher struct { 30 queue eventQueue 31 mu sync.RWMutex 32 } 33 34 func NewWatcher(capacity uint64) *Watcher { 35 return &Watcher{ 36 queue: eventQueue{ 37 Events: make([]*Event, capacity), 38 Capacity: capacity, 39 }, 40 } 41 } 42 43 func (w *Watcher) putEvent(e *Event) { 44 w.mu.Lock() 45 w.queue.push(e) 46 if w.queue.isFull() { 47 w.queue.frontTakeAStep() 48 } 49 w.mu.Unlock() 50 } 51 52 // getEvent if queue is empty, it will return nil. 53 func (w *Watcher) getEvent() *Event { 54 w.mu.RLock() 55 defer w.mu.RUnlock() 56 if w.queue.isEmpty() { 57 return nil 58 } 59 return w.queue.pop() 60 } 61 62 // sendEvent send events to DB's watch 63 func (w *Watcher) sendEvent(c chan *Event) { 64 for { 65 event := w.getEvent() 66 if event == nil { 67 time.Sleep(100 * time.Millisecond) 68 continue 69 } 70 c <- event 71 } 72 } 73 74 type eventQueue struct { 75 Events []*Event 76 Capacity uint64 77 Front uint64 // read point 78 Back uint64 // write point 79 } 80 81 func (eq *eventQueue) push(e *Event) { 82 eq.Events[eq.Back] = e 83 eq.Back = (eq.Back + 1) % eq.Capacity 84 } 85 86 func (eq *eventQueue) pop() *Event { 87 e := eq.Events[eq.Front] 88 eq.frontTakeAStep() 89 return e 90 } 91 92 func (eq *eventQueue) isFull() bool { 93 return (eq.Back+1)%eq.Capacity == eq.Front 94 } 95 96 func (eq *eventQueue) isEmpty() bool { 97 return eq.Back == eq.Front 98 } 99 100 func (eq *eventQueue) frontTakeAStep() { 101 eq.Front = (eq.Front + 1) % eq.Capacity 102 }