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

118 lines
2.7 KiB
Go

package model
import (
"context"
"sort"
"sync"
"spark-server/internal/module/favorite/entity"
"spark-server/internal/pkg/errs"
)
type userMsgKey struct {
UserID int64
MsgID int64
}
// MemoryRepo is an in-process favorite store for tests and empty-DSN bring-up.
type MemoryRepo struct {
mu sync.Mutex
byID map[int64]*entity.Favorite
byPair map[userMsgKey]int64
}
func NewMemoryRepo() *MemoryRepo {
return &MemoryRepo{byID: make(map[int64]*entity.Favorite), byPair: make(map[userMsgKey]int64)}
}
func (m *MemoryRepo) Get(_ context.Context, id int64) (*entity.Favorite, error) {
m.mu.Lock()
defer m.mu.Unlock()
row, ok := m.byID[id]
if !ok {
return nil, errs.ErrNotFound
}
return cloneFav(row), nil
}
func (m *MemoryRepo) GetByUserMsg(_ context.Context, userID, msgID int64) (*entity.Favorite, error) {
m.mu.Lock()
defer m.mu.Unlock()
id, ok := m.byPair[userMsgKey{UserID: userID, MsgID: msgID}]
if !ok {
return nil, errs.ErrNotFound
}
return cloneFav(m.byID[id]), nil
}
func (m *MemoryRepo) Create(_ context.Context, fav *entity.Favorite) error {
if fav == nil || fav.ID <= 0 || fav.UserID <= 0 {
return errs.ErrInvalidArgument
}
m.mu.Lock()
defer m.mu.Unlock()
key := userMsgKey{UserID: fav.UserID, MsgID: fav.MsgID}
if _, ok := m.byPair[key]; ok {
return errs.ErrDuplicate
}
if _, ok := m.byID[fav.ID]; ok {
return errs.ErrDuplicate
}
m.byID[fav.ID] = cloneFav(fav)
m.byPair[key] = fav.ID
return nil
}
func (m *MemoryRepo) ListByUser(_ context.Context, userID int64, limit int) ([]*entity.Favorite, error) {
m.mu.Lock()
defer m.mu.Unlock()
limit = entity.ClampLimit(limit)
out := make([]*entity.Favorite, 0)
for _, row := range m.byID {
if row.UserID == userID {
out = append(out, cloneFav(row))
}
}
sort.Slice(out, func(i, j int) bool { return out[i].ID > out[j].ID })
if len(out) > limit {
out = out[:limit]
}
return out, nil
}
func (m *MemoryRepo) ListAllByUser(_ context.Context, userID int64) ([]*entity.Favorite, error) {
m.mu.Lock()
defer m.mu.Unlock()
out := make([]*entity.Favorite, 0)
for _, row := range m.byID {
if row.UserID == userID {
out = append(out, cloneFav(row))
}
}
sort.Slice(out, func(i, j int) bool { return out[i].ID > out[j].ID })
return out, nil
}
func (m *MemoryRepo) Delete(_ context.Context, userID, id int64) error {
m.mu.Lock()
defer m.mu.Unlock()
row, ok := m.byID[id]
if !ok || row.UserID != userID {
return errs.ErrNotFound
}
delete(m.byID, id)
delete(m.byPair, userMsgKey{UserID: row.UserID, MsgID: row.MsgID})
return nil
}
func cloneFav(f *entity.Favorite) *entity.Favorite {
if f == nil {
return nil
}
cp := *f
if f.Content != nil {
cp.Content = append([]byte(nil), f.Content...)
}
return &cp
}