spark-server/internal/module/sync/model/memory.go
2026-09-20 17:49:09 +08:00

119 lines
2.5 KiB
Go

package model
import (
"context"
"sync"
"spark-server/internal/module/sync/entity"
)
type memEvent struct {
entity.MailboxItem
UserID int64
DeviceID int64
}
type memCursor struct {
MailboxSeq int64
DialogScore int64
}
// MemoryStore is an in-process mailbox for tests and empty-DSN bring-up.
type MemoryStore struct {
mu sync.Mutex
seq map[int64]int64
events []memEvent
cursors map[[2]int64]memCursor
ids IDGen
}
func NewMemoryStore(ids IDGen) *MemoryStore {
return &MemoryStore{
seq: make(map[int64]int64),
cursors: make(map[[2]int64]memCursor),
ids: ids,
}
}
func (s *MemoryStore) Put(_ context.Context, userID int64, eventType entity.EventType, conversationID int64, payload []byte) error {
if s == nil || userID <= 0 || eventType == 0 {
return nil
}
if s.ids != nil {
if _, err := s.ids.NextID(); err != nil {
return err
}
}
s.mu.Lock()
defer s.mu.Unlock()
s.seq[userID]++
s.events = append(s.events, memEvent{
UserID: userID, DeviceID: 0,
MailboxItem: entity.MailboxItem{
Seq: s.seq[userID], EventType: eventType, ConversationID: conversationID, Payload: append([]byte(nil), payload...),
},
})
return nil
}
func (s *MemoryStore) ListSince(_ context.Context, userID int64, deviceID uint64, seq int64, limit int) ([]*entity.MailboxItem, error) {
if s == nil || userID <= 0 {
return nil, nil
}
if limit <= 0 {
limit = 200
}
s.mu.Lock()
defer s.mu.Unlock()
out := make([]*entity.MailboxItem, 0)
did := int64(deviceID)
for i := range s.events {
ev := s.events[i]
if ev.UserID != userID || ev.Seq <= seq {
continue
}
if ev.DeviceID != 0 && ev.DeviceID != did {
continue
}
item := ev.MailboxItem
item.Payload = append([]byte(nil), ev.Payload...)
out = append(out, &item)
if len(out) >= limit {
break
}
}
return out, nil
}
func (s *MemoryStore) SaveCursor(_ context.Context, userID int64, deviceID uint64, mailboxSeq, dialogScore int64) error {
if s == nil || userID <= 0 || deviceID == 0 {
return nil
}
s.mu.Lock()
defer s.mu.Unlock()
s.cursors[[2]int64{userID, int64(deviceID)}] = memCursor{MailboxSeq: mailboxSeq, DialogScore: dialogScore}
return nil
}
func (s *MemoryStore) PurgeUser(_ context.Context, userID int64) error {
if s == nil || userID <= 0 {
return nil
}
s.mu.Lock()
defer s.mu.Unlock()
delete(s.seq, userID)
kept := s.events[:0]
for i := range s.events {
if s.events[i].UserID != userID {
kept = append(kept, s.events[i])
}
}
s.events = kept
for key := range s.cursors {
if key[0] == userID {
delete(s.cursors, key)
}
}
return nil
}