thread-master/apps/backend/internal/module/inspire/repository/mongo.go

178 lines
5.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"context"
libmongo "apps/backend/internal/lib/mongo"
"apps/backend/internal/module/inspire/domain"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
type MonStore struct {
trends *mon.Model
elements *mon.Model
sessions *mon.Model
active *mon.Model // inspire_session_active: _id=owner_uid, session_id
}
func NewMonStore(uri, database string) *MonStore {
uri = libmongo.MustMongoURI(uri)
return &MonStore{
trends: mon.MustNewModel(uri, database, "inspire_trends"),
elements: mon.MustNewModel(uri, database, "inspire_elements"),
sessions: mon.MustNewModel(uri, database, "inspire_sessions"),
active: mon.MustNewModel(uri, database, "inspire_session_active"),
}
}
type trendBag struct {
OwnerUID int64 `bson:"_id"`
Items []*domain.TrendItem `bson:"items"`
}
type activeRef struct {
OwnerUID int64 `bson:"_id"`
SessionID string `bson:"session_id"`
}
func (s *MonStore) ListTrends(ctx context.Context, ownerUID int64) ([]*domain.TrendItem, error) {
var bag trendBag
err := s.trends.FindOne(ctx, &bag, bson.M{"_id": ownerUID})
if err != nil {
if err == mon.ErrNotFound {
return nil, nil
}
return nil, err
}
return bag.Items, nil
}
func (s *MonStore) SaveTrends(ctx context.Context, ownerUID int64, items []*domain.TrendItem) error {
bag := trendBag{OwnerUID: ownerUID, Items: items}
_, err := s.trends.ReplaceOne(ctx, bson.M{"_id": ownerUID}, bag, options.Replace().SetUpsert(true))
return err
}
func (s *MonStore) ListElements(ctx context.Context, ownerUID int64) ([]*domain.Element, error) {
var list []*domain.Element
err := s.elements.Find(ctx, &list, bson.M{"owner_uid": ownerUID},
options.Find().SetSort(bson.D{{Key: "updated_at", Value: -1}}))
return list, err
}
func (s *MonStore) SaveElement(ctx context.Context, e *domain.Element) error {
_, err := s.elements.ReplaceOne(ctx, bson.M{"_id": e.ID}, e, options.Replace().SetUpsert(true))
return err
}
func (s *MonStore) DeleteElement(ctx context.Context, id string) error {
res, err := s.elements.DeleteOne(ctx, bson.M{"_id": id})
if err != nil {
return err
}
if res == 0 {
return domain.ErrNotFound
}
return nil
}
func (s *MonStore) GetElement(ctx context.Context, id string) (*domain.Element, error) {
var e domain.Element
err := s.elements.FindOne(ctx, &e, bson.M{"_id": id})
if err != nil {
if err == mon.ErrNotFound {
return nil, domain.ErrNotFound
}
return nil, err
}
return &e, nil
}
func (s *MonStore) ListSessions(ctx context.Context, ownerUID int64) ([]*domain.Session, error) {
var list []*domain.Session
err := s.sessions.Find(ctx, &list, bson.M{"owner_uid": ownerUID},
options.Find().SetSort(bson.D{{Key: "updated_at", Value: -1}}).SetLimit(50))
if err != nil {
return nil, err
}
return list, nil
}
// GetSession — active無 active失效則取最近一則都沒有回 NotFoundusecase 建新)。
func (s *MonStore) GetSession(ctx context.Context, ownerUID int64) (*domain.Session, error) {
if id, err := s.GetActiveSessionID(ctx, ownerUID); err == nil && id != "" {
if sess, gerr := s.GetSessionByID(ctx, ownerUID, id); gerr == nil {
return sess, nil
}
}
// fallback最近更新
var list []*domain.Session
err := s.sessions.Find(ctx, &list, bson.M{"owner_uid": ownerUID},
options.Find().SetSort(bson.D{{Key: "updated_at", Value: -1}}).SetLimit(1))
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, domain.ErrNotFound
}
_ = s.SetActiveSessionID(ctx, ownerUID, list[0].ID)
return list[0], nil
}
func (s *MonStore) GetSessionByID(ctx context.Context, ownerUID int64, id string) (*domain.Session, error) {
var sess domain.Session
err := s.sessions.FindOne(ctx, &sess, bson.M{"_id": id, "owner_uid": ownerUID})
if err != nil {
if err == mon.ErrNotFound {
return nil, domain.ErrNotFound
}
return nil, err
}
return &sess, nil
}
func (s *MonStore) SaveSession(ctx context.Context, sess *domain.Session) error {
// 用 _id + owner_uid多 session 且禁止覆寫別人的對話
_, err := s.sessions.ReplaceOne(
ctx,
bson.M{"_id": sess.ID, "owner_uid": sess.OwnerUID},
sess,
options.Replace().SetUpsert(true),
)
return err
}
func (s *MonStore) DeleteSessionByID(ctx context.Context, ownerUID int64, id string) error {
res, err := s.sessions.DeleteOne(ctx, bson.M{"_id": id, "owner_uid": ownerUID})
if err != nil {
return err
}
if res == 0 {
return domain.ErrNotFound
}
return nil
}
func (s *MonStore) GetActiveSessionID(ctx context.Context, ownerUID int64) (string, error) {
var ref activeRef
err := s.active.FindOne(ctx, &ref, bson.M{"_id": ownerUID})
if err != nil {
if err == mon.ErrNotFound {
return "", domain.ErrNotFound
}
return "", err
}
return ref.SessionID, nil
}
func (s *MonStore) SetActiveSessionID(ctx context.Context, ownerUID int64, sessionID string) error {
ref := activeRef{OwnerUID: ownerUID, SessionID: sessionID}
_, err := s.active.ReplaceOne(ctx, bson.M{"_id": ownerUID}, ref, options.Replace().SetUpsert(true))
return err
}
var _ domain.Repository = (*MonStore)(nil)