thread-master/apps/backend/internal/module/appnotif/repository/memory.go

125 lines
2.5 KiB
Go

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)