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

178 lines
5.1 KiB
Go
Raw Permalink Normal View History

2026-07-13 01:15:30 +00:00
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)