package repository import ( "context" "sync" "apps/backend/internal/module/appnotif/domain" ) type MemoryStore struct { mu sync.Mutex byID map[string]*domain.Notification } func NewMemory() *MemoryStore { return &MemoryStore{byID: map[string]*domain.Notification{}} } func (s *MemoryStore) Insert(_ context.Context, n *domain.Notification) error { s.mu.Lock() defer s.mu.Unlock() cp := *n s.byID[n.ID] = &cp return nil } func (s *MemoryStore) ListByOwner(_ context.Context, ownerUID int64) ([]*domain.Notification, error) { s.mu.Lock() defer s.mu.Unlock() var out []*domain.Notification for _, n := range s.byID { if n.OwnerUID == ownerUID { cp := *n out = append(out, &cp) } } return out, nil } func (s *MemoryStore) UnreadCount(_ context.Context, ownerUID int64) (int64, error) { s.mu.Lock() defer s.mu.Unlock() var c int64 for _, n := range s.byID { if n.OwnerUID == ownerUID && n.ReadAt == 0 { c++ } } return c, nil } func (s *MemoryStore) FindByID(_ context.Context, id string) (*domain.Notification, error) { s.mu.Lock() defer s.mu.Unlock() n, ok := s.byID[id] if !ok { return nil, domain.ErrNotFound } cp := *n return &cp, nil } func (s *MemoryStore) MarkRead(_ context.Context, ownerUID int64, id string) error { s.mu.Lock() defer s.mu.Unlock() n, ok := s.byID[id] if !ok { return domain.ErrNotFound } if n.OwnerUID != ownerUID { return domain.ErrForbidden } if n.ReadAt == 0 { n.ReadAt = domain.NowNano() } return nil } func (s *MemoryStore) MarkAllRead(_ context.Context, ownerUID int64) error { s.mu.Lock() defer s.mu.Unlock() now := domain.NowNano() for _, n := range s.byID { if n.OwnerUID == ownerUID && n.ReadAt == 0 { n.ReadAt = now } } return nil } func (s *MemoryStore) FindLatestByJobRef(_ context.Context, ownerUID int64, jobID string) (*domain.Notification, error) { s.mu.Lock() defer s.mu.Unlock() var best *domain.Notification for _, n := range s.byID { if n.OwnerUID != ownerUID || n.Kind != domain.KindJob || n.RefType != domain.RefJob || n.RefID != jobID { continue } if best == nil || n.CreatedAt > best.CreatedAt { cp := *n best = &cp } } if best == nil { return nil, domain.ErrNotFound } return best, nil } func (s *MemoryStore) Replace(_ context.Context, n *domain.Notification) error { s.mu.Lock() defer s.mu.Unlock() if n == nil || n.ID == "" { return domain.ErrNotFound } if _, ok := s.byID[n.ID]; !ok { return domain.ErrNotFound } cp := *n s.byID[n.ID] = &cp return nil } var _ domain.Repository = (*MemoryStore)(nil)