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 }