package server import ( _ "github.com/mattn/go-sqlite3" // SQLite driver "sync" "time" ) type memCache struct { messages map[string][]*message mu sync.Mutex } var _ cache = (*memCache)(nil) func newMemCache() *memCache { return &memCache{ messages: make(map[string][]*message), } } func (s *memCache) AddMessage(m *message) error { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.messages[m.Topic]; !ok { s.messages[m.Topic] = make([]*message, 0) } s.messages[m.Topic] = append(s.messages[m.Topic], m) return nil } func (s *memCache) Messages(topic string, since sinceTime) ([]*message, error) { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.messages[topic]; !ok { return make([]*message, 0), nil } messages := make([]*message, 0) // copy! for _, m := range s.messages[topic] { msgTime := time.Unix(m.Time, 0) if msgTime == since.Time() || msgTime.After(since.Time()) { messages = append(messages, m) } } return messages, nil } func (s *memCache) MessageCount(topic string) (int, error) { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.messages[topic]; !ok { return 0, nil } return len(s.messages[topic]), nil } func (s *memCache) Topics() (map[string]*topic, error) { // Hack since we know when this is called there are no messages! return make(map[string]*topic), nil } func (s *memCache) Prune(keep time.Duration) error { s.mu.Lock() defer s.mu.Unlock() for topic, _ := range s.messages { s.pruneTopic(topic, keep) } return nil } func (s *memCache) pruneTopic(topic string, keep time.Duration) { for i, m := range s.messages[topic] { msgTime := time.Unix(m.Time, 0) if time.Since(msgTime) < keep { s.messages[topic] = s.messages[topic][i:] return } } s.messages[topic] = make([]*message, 0) // all messages expired }