2021-11-05 14:27:30 +00:00
|
|
|
package store
|
|
|
|
|
2021-11-06 20:57:19 +00:00
|
|
|
import (
|
2022-01-18 18:17:06 +00:00
|
|
|
"errors"
|
2021-11-06 20:57:19 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/status-im/go-waku/waku/v2/utils"
|
|
|
|
)
|
|
|
|
|
2021-11-05 14:27:30 +00:00
|
|
|
type MessageQueue struct {
|
2021-11-06 20:57:19 +00:00
|
|
|
sync.RWMutex
|
|
|
|
|
|
|
|
seen map[[32]byte]struct{}
|
2021-11-05 14:27:30 +00:00
|
|
|
messages []IndexedWakuMessage
|
|
|
|
maxMessages int
|
2021-11-06 20:57:19 +00:00
|
|
|
maxDuration time.Duration
|
|
|
|
|
|
|
|
quit chan struct{}
|
2021-11-23 15:03:12 +00:00
|
|
|
wg *sync.WaitGroup
|
2021-11-06 20:57:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-18 18:17:06 +00:00
|
|
|
var ErrDuplicatedMessage = errors.New("duplicated message")
|
|
|
|
|
|
|
|
func (self *MessageQueue) Push(msg IndexedWakuMessage) error {
|
2021-11-06 20:57:19 +00:00
|
|
|
self.Lock()
|
|
|
|
defer self.Unlock()
|
|
|
|
|
|
|
|
var k [32]byte
|
|
|
|
copy(k[:], msg.index.Digest)
|
|
|
|
if _, ok := self.seen[k]; ok {
|
2022-01-18 18:17:06 +00:00
|
|
|
return ErrDuplicatedMessage
|
2021-11-06 20:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.seen[k] = struct{}{}
|
2021-11-05 14:27:30 +00:00
|
|
|
self.messages = append(self.messages, msg)
|
|
|
|
|
|
|
|
if self.maxMessages != 0 && len(self.messages) > self.maxMessages {
|
|
|
|
numToPop := len(self.messages) - self.maxMessages
|
|
|
|
self.messages = self.messages[numToPop:len(self.messages)]
|
|
|
|
}
|
2022-01-18 18:17:06 +00:00
|
|
|
|
|
|
|
return nil
|
2021-11-05 14:27:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-06 22:46:58 +00:00
|
|
|
func (self *MessageQueue) Messages() <-chan IndexedWakuMessage {
|
|
|
|
c := make(chan IndexedWakuMessage)
|
2021-11-06 20:57:19 +00:00
|
|
|
|
|
|
|
f := func() {
|
|
|
|
self.RLock()
|
|
|
|
defer self.RUnlock()
|
2021-11-06 22:46:58 +00:00
|
|
|
for _, value := range self.messages {
|
|
|
|
c <- value
|
2021-11-06 20:57:19 +00:00
|
|
|
}
|
|
|
|
close(c)
|
|
|
|
}
|
|
|
|
go f()
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *MessageQueue) cleanOlderRecords() {
|
|
|
|
self.Lock()
|
|
|
|
defer self.Unlock()
|
|
|
|
|
|
|
|
// TODO: check if retention days was set
|
|
|
|
|
|
|
|
t := utils.GetUnixEpochFrom(time.Now().Add(-self.maxDuration))
|
|
|
|
|
|
|
|
var idx int
|
|
|
|
for i := 0; i < len(self.messages); i++ {
|
|
|
|
if self.messages[i].index.ReceiverTime >= t {
|
|
|
|
idx = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.messages = self.messages[idx:]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *MessageQueue) checkForOlderRecords(d time.Duration) {
|
2021-11-23 15:03:12 +00:00
|
|
|
defer self.wg.Done()
|
|
|
|
|
2021-11-06 20:57:19 +00:00
|
|
|
ticker := time.NewTicker(d)
|
2021-11-19 23:51:18 +00:00
|
|
|
defer ticker.Stop()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-self.quit:
|
|
|
|
return
|
|
|
|
case <-ticker.C:
|
|
|
|
self.cleanOlderRecords()
|
|
|
|
}
|
2021-11-06 20:57:19 +00:00
|
|
|
}
|
2021-11-05 14:27:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-06 20:57:19 +00:00
|
|
|
func (self *MessageQueue) Length() int {
|
|
|
|
self.RLock()
|
|
|
|
defer self.RUnlock()
|
|
|
|
return len(self.messages)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewMessageQueue(maxMessages int, maxDuration time.Duration) *MessageQueue {
|
|
|
|
result := &MessageQueue{
|
2021-11-05 14:27:30 +00:00
|
|
|
maxMessages: maxMessages,
|
2021-11-06 20:57:19 +00:00
|
|
|
maxDuration: maxDuration,
|
|
|
|
seen: make(map[[32]byte]struct{}),
|
|
|
|
quit: make(chan struct{}),
|
2021-11-23 15:03:12 +00:00
|
|
|
wg: &sync.WaitGroup{},
|
2021-11-06 20:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if maxDuration != 0 {
|
2021-11-23 15:03:12 +00:00
|
|
|
result.wg.Add(1)
|
2021-11-06 20:57:19 +00:00
|
|
|
go result.checkForOlderRecords(10 * time.Second) // is 10s okay?
|
2021-11-05 14:27:30 +00:00
|
|
|
}
|
2021-11-06 20:57:19 +00:00
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *MessageQueue) Stop() {
|
|
|
|
close(self.quit)
|
2021-11-23 15:03:12 +00:00
|
|
|
self.wg.Wait()
|
2021-11-05 14:27:30 +00:00
|
|
|
}
|