backend/pkg/member/repository/account.go

158 lines
3.9 KiB
Go

package repository
import (
"context"
"errors"
"time"
"backend/pkg/member/domain/member"
"backend/pkg/member/domain"
"backend/pkg/member/domain/entity"
"backend/pkg/member/domain/repository"
"backend/pkg/library/mongo"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/v2/bson"
mongodriver "go.mongodb.org/mongo-driver/v2/mongo"
)
type AccountRepositoryParam struct {
Conf *mongo.Conf
CacheConf cache.CacheConf
DBOpts []mon.Option
CacheOpts []cache.Option
}
type AccountRepository struct {
DB mongo.DocumentDBWithCacheUseCase
}
func NewAccountRepository(param AccountRepositoryParam) repository.AccountRepository {
e := entity.Account{}
documentDB, err := mongo.MustDocumentDBWithCache(
param.Conf,
e.CollectionName(),
param.CacheConf,
param.DBOpts,
param.CacheOpts,
)
if err != nil {
panic(err)
}
return &AccountRepository{
DB: documentDB,
}
}
func (repo *AccountRepository) Insert(ctx context.Context, data *entity.Account) error {
if data.ID.IsZero() {
now := time.Now().UTC().UnixNano()
data.ID = bson.NewObjectID()
data.CreateAt = &now
data.UpdateAt = &now
}
rk := domain.GetAccountRedisKey(data.ID.Hex())
_, err := repo.DB.InsertOne(ctx, rk, data)
return err
}
func (repo *AccountRepository) FindOne(ctx context.Context, id string) (*entity.Account, error) {
oid, err := bson.ObjectIDFromHex(id)
if err != nil {
return nil, ErrInvalidObjectID
}
var data entity.Account
rk := domain.GetAccountRedisKey(id)
err = repo.DB.FindOne(ctx, rk, &data, bson.M{"_id": oid})
switch {
case err == nil:
return &data, nil
case errors.Is(err, mon.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
func (repo *AccountRepository) Update(ctx context.Context, data *entity.Account) (*mongodriver.UpdateResult, error) {
now := time.Now().UTC().UnixNano()
data.UpdateAt = &now
rk := domain.GetAccountRedisKey(data.ID.Hex())
res, err := repo.DB.UpdateOne(ctx, rk, bson.M{"_id": data.ID}, bson.M{"$set": data})
return res, err
}
func (repo *AccountRepository) Delete(ctx context.Context, id string) (int64, error) {
oid, err := bson.ObjectIDFromHex(id)
if err != nil {
return 0, ErrInvalidObjectID
}
rk := domain.GetAccountRedisKey(id)
return repo.DB.DeleteOne(ctx, rk, bson.M{"_id": oid})
}
func (repo *AccountRepository) FindOneByAccount(ctx context.Context, loginID string) (*entity.Account, error) {
// todo: 之後需要同步快取
var data entity.Account
err := repo.DB.GetClient().FindOne(ctx, &data, bson.M{"login_id": loginID})
switch {
case err == nil:
return &data, nil
case errors.Is(err, mon.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
func (repo *AccountRepository) UpdateTokenByLoginID(ctx context.Context, account string, token string, platform member.Platform) error {
// todo: 之後需要同步快取
filter := bson.M{"login_id": account, "platform": platform.ToInt64()}
update := bson.M{
"$set": bson.M{
"token": token,
"update_at": time.Now().UTC().UnixNano(),
},
}
var data entity.Account
err := repo.DB.GetClient().FindOne(ctx, &data, filter)
if err != nil {
return err
}
rk := domain.GetAccountRedisKey(data.ID.Hex())
modify, err := repo.DB.UpdateOne(ctx, rk, bson.M{"_id": data.ID}, update)
if err != nil {
return err
}
if modify.MatchedCount == 0 {
return ErrNotFound // 自定義的錯誤表示未找到記錄
}
return nil
}
func (repo *AccountRepository) Index20241226001UP(ctx context.Context) (*mongodriver.Cursor, error) {
// 等價於 db.account.createIndex({ "login_id": 1, "platform": 1}, {unique: true})
repo.DB.PopulateMultiIndex(ctx, []string{
"login_id",
"platform",
}, []int32{1, 1}, true)
// 等價於 db.account.createIndex({"create_at": 1})
repo.DB.PopulateIndex(ctx, "create_at", 1, false)
return repo.DB.GetClient().Indexes().List(ctx)
}