spark-server/internal/module/inbox/model/memory.go
2026-09-18 14:50:41 +08:00

123 lines
2.9 KiB
Go

package model
import (
"context"
"sync"
"spark-server/internal/module/inbox/entity"
)
type dialog struct {
unread map[int64]int64
read map[int64]int64
unreadCnt map[int64]int64
}
// MemoryStore is an in-process inbox for tests.
type MemoryStore struct {
mu sync.Mutex
byUser map[int64]*dialog
previews map[int64][]byte
}
func NewMemoryStore() *MemoryStore {
return &MemoryStore{byUser: make(map[int64]*dialog), previews: make(map[int64][]byte)}
}
func (s *MemoryStore) user(uid int64) *dialog {
d, ok := s.byUser[uid]
if !ok {
d = &dialog{unread: map[int64]int64{}, read: map[int64]int64{}, unreadCnt: map[int64]int64{}}
s.byUser[uid] = d
}
return d
}
func (s *MemoryStore) TouchUnread(_ context.Context, userID, conversationID, score int64) error {
s.mu.Lock()
defer s.mu.Unlock()
d := s.user(userID)
delete(d.read, conversationID)
d.unread[conversationID] = score
return nil
}
func (s *MemoryStore) TouchRead(_ context.Context, userID, conversationID, score int64) error {
s.mu.Lock()
defer s.mu.Unlock()
d := s.user(userID)
delete(d.unread, conversationID)
d.read[conversationID] = score
return nil
}
func (s *MemoryStore) IncrUnread(_ context.Context, userID, conversationID, delta int64) error {
s.mu.Lock()
defer s.mu.Unlock()
d := s.user(userID)
d.unreadCnt[conversationID] += delta
return nil
}
func (s *MemoryStore) SetPreview(_ context.Context, conversationID int64, preview []byte) error {
s.mu.Lock()
defer s.mu.Unlock()
s.previews[conversationID] = append([]byte(nil), preview...)
return nil
}
func (s *MemoryStore) ListUpdatedSince(_ context.Context, userID, score int64, limit int) ([]entity.DialogHit, error) {
s.mu.Lock()
defer s.mu.Unlock()
d := s.user(userID)
var out []entity.DialogHit
seen := map[int64]struct{}{}
add := func(cid, sc int64) {
if sc <= score {
return
}
if _, ok := seen[cid]; ok {
return
}
seen[cid] = struct{}{}
out = append(out, entity.DialogHit{ConversationID: cid, Score: sc})
}
for cid, sc := range d.unread {
add(cid, sc)
}
for cid, sc := range d.read {
add(cid, sc)
}
if limit > 0 && len(out) > limit {
out = out[:limit]
}
return out, nil
}
func (s *MemoryStore) LoadDialogs(_ context.Context, userID int64, hits []entity.DialogHit) ([]entity.Dialog, error) {
s.mu.Lock()
defer s.mu.Unlock()
out := make([]entity.Dialog, 0, len(hits))
for _, hit := range hits {
out = append(out, entity.Dialog{
ConversationID: hit.ConversationID,
Score: hit.Score,
Unread: s.user(userID).unreadCnt[hit.ConversationID],
Preview: append([]byte(nil), s.previews[hit.ConversationID]...),
})
}
return out, nil
}
func (s *MemoryStore) Preview(conversationID int64) []byte {
s.mu.Lock()
defer s.mu.Unlock()
return append([]byte(nil), s.previews[conversationID]...)
}
func (s *MemoryStore) UnreadCount(userID, conversationID int64) int64 {
s.mu.Lock()
defer s.mu.Unlock()
return s.user(userID).unreadCnt[conversationID]
}