474 lines
15 KiB
Go
474 lines
15 KiB
Go
|
|
package repository
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
|
||
|
|
libmongo "apps/backend/internal/lib/mongo"
|
||
|
|
"apps/backend/internal/module/growth/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 {
|
||
|
|
outcomes *mon.Model
|
||
|
|
checkups *mon.Model
|
||
|
|
health *mon.Model
|
||
|
|
workspaces *mon.Model
|
||
|
|
wsState *mon.Model
|
||
|
|
reviews *mon.Model
|
||
|
|
rewards *mon.Model
|
||
|
|
playbooks *mon.Model
|
||
|
|
utm *mon.Model
|
||
|
|
wsMembers *mon.Model
|
||
|
|
bench *mon.Model
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewMonStore(uri, database string) *MonStore {
|
||
|
|
uri = libmongo.MustMongoURI(uri)
|
||
|
|
return &MonStore{
|
||
|
|
outcomes: mon.MustNewModel(uri, database, "growth_outcomes"),
|
||
|
|
checkups: mon.MustNewModel(uri, database, "growth_checkups"),
|
||
|
|
health: mon.MustNewModel(uri, database, "growth_account_health"),
|
||
|
|
workspaces: mon.MustNewModel(uri, database, "growth_workspaces"),
|
||
|
|
wsState: mon.MustNewModel(uri, database, "growth_ws_state"),
|
||
|
|
reviews: mon.MustNewModel(uri, database, "growth_draft_reviews"),
|
||
|
|
rewards: mon.MustNewModel(uri, database, "growth_invite_rewards"),
|
||
|
|
playbooks: mon.MustNewModel(uri, database, "growth_playbooks"),
|
||
|
|
utm: mon.MustNewModel(uri, database, "growth_utm_links"),
|
||
|
|
wsMembers: mon.MustNewModel(uri, database, "growth_ws_members"),
|
||
|
|
bench: mon.MustNewModel(uri, database, "growth_benchmark"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) UpsertOutcomeBySource(ctx context.Context, e *domain.OutcomeEvent) error {
|
||
|
|
filter := bson.M{"owner_uid": e.OwnerUID, "source_type": e.SourceType, "source_id": e.SourceID}
|
||
|
|
var existing domain.OutcomeEvent
|
||
|
|
err := s.outcomes.FindOne(ctx, &existing, filter)
|
||
|
|
if err == nil {
|
||
|
|
// 發佈 hook 可能重送;已存在就保持原 sent_at 與所有觀測/成交訊號。
|
||
|
|
*e = existing
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if err != mon.ErrNotFound {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if e.ID == "" {
|
||
|
|
e.ID = domain.NewID()
|
||
|
|
}
|
||
|
|
_, err = s.outcomes.InsertOne(ctx, e)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetOutcome(ctx context.Context, id string) (*domain.OutcomeEvent, error) {
|
||
|
|
var e domain.OutcomeEvent
|
||
|
|
err := s.outcomes.FindOne(ctx, &e, bson.M{"_id": id})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &e, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListOutcomes(ctx context.Context, ownerUID int64, f domain.OutcomeListFilter) ([]*domain.OutcomeEvent, int64, error) {
|
||
|
|
q := bson.M{"owner_uid": ownerUID}
|
||
|
|
if f.Kind != "" {
|
||
|
|
q["kind"] = f.Kind
|
||
|
|
}
|
||
|
|
if f.Confidence != "" {
|
||
|
|
q["confidence"] = f.Confidence
|
||
|
|
}
|
||
|
|
if f.SourceType != "" {
|
||
|
|
q["source_type"] = f.SourceType
|
||
|
|
}
|
||
|
|
if f.From > 0 || f.To > 0 {
|
||
|
|
rangeQ := bson.M{}
|
||
|
|
if f.From > 0 {
|
||
|
|
rangeQ["$gte"] = f.From
|
||
|
|
}
|
||
|
|
if f.To > 0 {
|
||
|
|
rangeQ["$lte"] = f.To
|
||
|
|
}
|
||
|
|
q["sent_at"] = rangeQ
|
||
|
|
}
|
||
|
|
total, err := s.outcomes.CountDocuments(ctx, q)
|
||
|
|
if err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
page, ps := f.Page, f.PageSize
|
||
|
|
if page < 1 {
|
||
|
|
page = 1
|
||
|
|
}
|
||
|
|
if ps < 1 {
|
||
|
|
ps = 20
|
||
|
|
}
|
||
|
|
var list []*domain.OutcomeEvent
|
||
|
|
err = s.outcomes.Find(ctx, &list, q, options.Find().
|
||
|
|
SetSort(bson.D{{Key: "sent_at", Value: -1}}).
|
||
|
|
SetSkip(int64((page-1)*ps)).
|
||
|
|
SetLimit(int64(ps)))
|
||
|
|
return list, total, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveOutcome(ctx context.Context, e *domain.OutcomeEvent) error {
|
||
|
|
_, err := s.outcomes.UpdateOne(ctx, bson.M{"_id": e.ID}, bson.M{"$set": e}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListObservingDue(ctx context.Context, now int64, limit int) ([]*domain.OutcomeEvent, error) {
|
||
|
|
var list []*domain.OutcomeEvent
|
||
|
|
opts := options.Find().SetSort(bson.D{{Key: "sent_at", Value: 1}})
|
||
|
|
if limit > 0 {
|
||
|
|
opts.SetLimit(int64(limit))
|
||
|
|
}
|
||
|
|
err := s.outcomes.Find(ctx, &list, bson.M{"status": domain.StatusObserving}, opts)
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveCheckup(ctx context.Context, c *domain.WeeklyCheckup) error {
|
||
|
|
_, err := s.checkups.UpdateOne(ctx, bson.M{"_id": c.ID}, bson.M{"$set": c}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetCheckup(ctx context.Context, id string) (*domain.WeeklyCheckup, error) {
|
||
|
|
var c domain.WeeklyCheckup
|
||
|
|
err := s.checkups.FindOne(ctx, &c, bson.M{"_id": id})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &c, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) LatestCheckup(ctx context.Context, ownerUID int64) (*domain.WeeklyCheckup, error) {
|
||
|
|
var list []*domain.WeeklyCheckup
|
||
|
|
err := s.checkups.Find(ctx, &list, bson.M{"owner_uid": ownerUID},
|
||
|
|
options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}}).SetLimit(1))
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if len(list) == 0 {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return list[0], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListCheckups(ctx context.Context, ownerUID int64, page, pageSize int) ([]*domain.WeeklyCheckup, int64, error) {
|
||
|
|
q := bson.M{"owner_uid": ownerUID}
|
||
|
|
total, err := s.checkups.CountDocuments(ctx, q)
|
||
|
|
if err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
if page < 1 {
|
||
|
|
page = 1
|
||
|
|
}
|
||
|
|
if pageSize < 1 {
|
||
|
|
pageSize = 20
|
||
|
|
}
|
||
|
|
var list []*domain.WeeklyCheckup
|
||
|
|
err = s.checkups.Find(ctx, &list, q, options.Find().
|
||
|
|
SetSort(bson.D{{Key: "created_at", Value: -1}}).
|
||
|
|
SetSkip(int64((page-1)*pageSize)).SetLimit(int64(pageSize)))
|
||
|
|
return list, total, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) CountCheckupGenerations(ctx context.Context, ownerUID int64, sinceNano int64) (int64, error) {
|
||
|
|
return s.checkups.CountDocuments(ctx, bson.M{"owner_uid": ownerUID, "created_at": bson.M{"$gte": sinceNano}})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveHealth(ctx context.Context, h *domain.AccountHealth) error {
|
||
|
|
_, err := s.health.UpdateOne(ctx, bson.M{"_id": h.ThreadsAccountID}, bson.M{"$set": h}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetHealth(ctx context.Context, accountID string) (*domain.AccountHealth, error) {
|
||
|
|
var h domain.AccountHealth
|
||
|
|
err := s.health.FindOne(ctx, &h, bson.M{"_id": accountID})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &h, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListHealth(ctx context.Context, ownerUID int64) ([]*domain.AccountHealth, error) {
|
||
|
|
var list []*domain.AccountHealth
|
||
|
|
err := s.health.Find(ctx, &list, bson.M{"owner_uid": ownerUID})
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveWorkspace(ctx context.Context, w *domain.Workspace) error {
|
||
|
|
_, err := s.workspaces.UpdateOne(ctx, bson.M{"_id": w.ID}, bson.M{"$set": w}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetWorkspace(ctx context.Context, id string) (*domain.Workspace, error) {
|
||
|
|
var w domain.Workspace
|
||
|
|
err := s.workspaces.FindOne(ctx, &w, bson.M{"_id": id})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &w, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListWorkspaces(ctx context.Context, ownerUID int64, includeArchived bool) ([]*domain.Workspace, error) {
|
||
|
|
q := bson.M{"owner_uid": ownerUID}
|
||
|
|
if !includeArchived {
|
||
|
|
q["archived"] = bson.M{"$ne": true}
|
||
|
|
}
|
||
|
|
var list []*domain.Workspace
|
||
|
|
err := s.workspaces.Find(ctx, &list, q, options.Find().SetSort(bson.D{{Key: "created_at", Value: 1}}))
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) CountActiveWorkspaces(ctx context.Context, ownerUID int64) (int64, error) {
|
||
|
|
return s.workspaces.CountDocuments(ctx, bson.M{"owner_uid": ownerUID, "archived": bson.M{"$ne": true}})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetMemberWSState(ctx context.Context, ownerUID int64) (*domain.MemberWorkspaceState, error) {
|
||
|
|
var st domain.MemberWorkspaceState
|
||
|
|
err := s.wsState.FindOne(ctx, &st, bson.M{"_id": ownerUID})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &st, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveMemberWSState(ctx context.Context, st *domain.MemberWorkspaceState) error {
|
||
|
|
_, err := s.wsState.UpdateOne(ctx, bson.M{"_id": st.OwnerUID}, bson.M{"$set": st}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveReview(ctx context.Context, r *domain.DraftReview) error {
|
||
|
|
_, err := s.reviews.UpdateOne(ctx, bson.M{"_id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) GetReview(ctx context.Context, id string) (*domain.DraftReview, error) {
|
||
|
|
var r domain.DraftReview
|
||
|
|
err := s.reviews.FindOne(ctx, &r, bson.M{"_id": id})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &r, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) FindReviewByRef(ctx context.Context, ownerUID int64, refType, refID string) (*domain.DraftReview, error) {
|
||
|
|
var list []*domain.DraftReview
|
||
|
|
err := s.reviews.Find(ctx, &list, bson.M{"owner_uid": ownerUID, "ref_type": refType, "ref_id": refID},
|
||
|
|
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
|
||
|
|
}
|
||
|
|
return list[0], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListReviews(ctx context.Context, ownerUID int64, status string, page, pageSize int) ([]*domain.DraftReview, int64, error) {
|
||
|
|
q := bson.M{"owner_uid": ownerUID}
|
||
|
|
if status != "" {
|
||
|
|
q["status"] = status
|
||
|
|
}
|
||
|
|
total, err := s.reviews.CountDocuments(ctx, q)
|
||
|
|
if err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
if page < 1 {
|
||
|
|
page = 1
|
||
|
|
}
|
||
|
|
if pageSize < 1 {
|
||
|
|
pageSize = 20
|
||
|
|
}
|
||
|
|
var list []*domain.DraftReview
|
||
|
|
err = s.reviews.Find(ctx, &list, q, options.Find().SetSkip(int64((page-1)*pageSize)).SetLimit(int64(pageSize)))
|
||
|
|
return list, total, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SaveInviteReward(ctx context.Context, r *domain.InviteReward) error {
|
||
|
|
_, err := s.rewards.InsertOne(ctx, r)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) ListInviteRewards(ctx context.Context, inviterUID int64, limit int) ([]*domain.InviteReward, error) {
|
||
|
|
opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}})
|
||
|
|
if limit > 0 {
|
||
|
|
opts.SetLimit(int64(limit))
|
||
|
|
}
|
||
|
|
var list []*domain.InviteReward
|
||
|
|
err := s.rewards.Find(ctx, &list, bson.M{"inviter_uid": inviterUID}, opts)
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SumInviteRewardPointsMonth(ctx context.Context, inviterUID int64, monthStartNano int64) (int, error) {
|
||
|
|
var list []*domain.InviteReward
|
||
|
|
err := s.rewards.Find(ctx, &list, bson.M{
|
||
|
|
"inviter_uid": inviterUID,
|
||
|
|
"status": domain.RewardCredited,
|
||
|
|
"created_at": bson.M{"$gte": monthStartNano},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return 0, err
|
||
|
|
}
|
||
|
|
sum := 0
|
||
|
|
for _, r := range list {
|
||
|
|
sum += r.Points
|
||
|
|
}
|
||
|
|
return sum, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) SumInviteRewardPointsTotal(ctx context.Context, inviterUID int64) (int, error) {
|
||
|
|
var list []*domain.InviteReward
|
||
|
|
err := s.rewards.Find(ctx, &list, bson.M{"inviter_uid": inviterUID, "status": domain.RewardCredited})
|
||
|
|
if err != nil {
|
||
|
|
return 0, err
|
||
|
|
}
|
||
|
|
sum := 0
|
||
|
|
for _, r := range list {
|
||
|
|
sum += r.Points
|
||
|
|
}
|
||
|
|
return sum, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MonStore) HasInviteRewardForInvitee(ctx context.Context, inviteeUID int64) (bool, error) {
|
||
|
|
n, err := s.rewards.CountDocuments(ctx, bson.M{
|
||
|
|
"invitee_uid": inviteeUID,
|
||
|
|
"status": bson.M{"$in": []string{domain.RewardCredited, domain.RewardCapped}},
|
||
|
|
})
|
||
|
|
return n > 0, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var _ domain.Repository = (*MonStore)(nil)
|
||
|
|
|
||
|
|
func (s *MonStore) SavePlaybook(ctx context.Context, p *domain.Playbook) error {
|
||
|
|
_, err := s.playbooks.UpdateOne(ctx, bson.M{"_id": p.ID}, bson.M{"$set": p}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
func (s *MonStore) GetPlaybook(ctx context.Context, id string) (*domain.Playbook, error) {
|
||
|
|
var p domain.Playbook
|
||
|
|
err := s.playbooks.FindOne(ctx, &p, bson.M{"_id": id})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &p, err
|
||
|
|
}
|
||
|
|
func (s *MonStore) ListPlaybooks(ctx context.Context, kind, niche string, ownerOnlyUID int64, page, pageSize int) ([]*domain.Playbook, int64, error) {
|
||
|
|
q := bson.M{}
|
||
|
|
if kind != "" {
|
||
|
|
q["kind"] = kind
|
||
|
|
}
|
||
|
|
if niche != "" {
|
||
|
|
q["niche"] = bson.M{"$regex": niche, "$options": "i"}
|
||
|
|
}
|
||
|
|
if ownerOnlyUID > 0 {
|
||
|
|
q["owner_uid"] = ownerOnlyUID
|
||
|
|
}
|
||
|
|
total, err := s.playbooks.CountDocuments(ctx, q)
|
||
|
|
if err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
if page < 1 {
|
||
|
|
page = 1
|
||
|
|
}
|
||
|
|
if pageSize < 1 {
|
||
|
|
pageSize = 20
|
||
|
|
}
|
||
|
|
var list []*domain.Playbook
|
||
|
|
err = s.playbooks.Find(ctx, &list, q, options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}}).SetSkip(int64((page-1)*pageSize)).SetLimit(int64(pageSize)))
|
||
|
|
return list, total, err
|
||
|
|
}
|
||
|
|
func (s *MonStore) DeletePlaybook(ctx context.Context, id string) error {
|
||
|
|
res, err := s.playbooks.DeleteOne(ctx, bson.M{"_id": id})
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if res == 0 {
|
||
|
|
return domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
func (s *MonStore) IncPlaybookImport(ctx context.Context, id string) error {
|
||
|
|
_, err := s.playbooks.UpdateOne(ctx, bson.M{"_id": id}, bson.M{"$inc": bson.M{"import_count": 1}})
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
func (s *MonStore) SaveUtmLink(ctx context.Context, u *domain.UtmLink) error {
|
||
|
|
_, err := s.utm.UpdateOne(ctx, bson.M{"_id": u.ID}, bson.M{"$set": u}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
func (s *MonStore) GetUtmByCode(ctx context.Context, code string) (*domain.UtmLink, error) {
|
||
|
|
var u domain.UtmLink
|
||
|
|
err := s.utm.FindOne(ctx, &u, bson.M{"code": code})
|
||
|
|
if err == mon.ErrNotFound {
|
||
|
|
return nil, domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return &u, err
|
||
|
|
}
|
||
|
|
func (s *MonStore) ListUtmLinks(ctx context.Context, ownerUID int64) ([]*domain.UtmLink, error) {
|
||
|
|
var list []*domain.UtmLink
|
||
|
|
err := s.utm.Find(ctx, &list, bson.M{"owner_uid": ownerUID}, options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}}))
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
func (s *MonStore) IncUtmClick(ctx context.Context, code string) (*domain.UtmLink, error) {
|
||
|
|
_, err := s.utm.UpdateOne(ctx, bson.M{"code": code}, bson.M{"$inc": bson.M{"clicks": 1}})
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return s.GetUtmByCode(ctx, code)
|
||
|
|
}
|
||
|
|
func (s *MonStore) SaveWorkspaceMember(ctx context.Context, m *domain.WorkspaceMember) error {
|
||
|
|
_, err := s.wsMembers.UpdateOne(ctx, bson.M{"_id": m.ID}, bson.M{"$set": m}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
func (s *MonStore) ListWorkspaceMembers(ctx context.Context, workspaceID string) ([]*domain.WorkspaceMember, error) {
|
||
|
|
var list []*domain.WorkspaceMember
|
||
|
|
err := s.wsMembers.Find(ctx, &list, bson.M{"workspace_id": workspaceID})
|
||
|
|
return list, err
|
||
|
|
}
|
||
|
|
func (s *MonStore) RemoveWorkspaceMember(ctx context.Context, workspaceID string, uid int64) error {
|
||
|
|
res, err := s.wsMembers.DeleteOne(ctx, bson.M{"workspace_id": workspaceID, "uid": uid})
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if res == 0 {
|
||
|
|
return domain.ErrNotFound
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
func (s *MonStore) IsWorkspaceMember(ctx context.Context, workspaceID string, uid int64) (bool, string, error) {
|
||
|
|
w, err := s.GetWorkspace(ctx, workspaceID)
|
||
|
|
if err == nil && w.OwnerUID == uid {
|
||
|
|
return true, domain.WSRoleOwner, nil
|
||
|
|
}
|
||
|
|
var list []*domain.WorkspaceMember
|
||
|
|
err = s.wsMembers.Find(ctx, &list, bson.M{"workspace_id": workspaceID, "uid": uid}, options.Find().SetLimit(1))
|
||
|
|
if err != nil {
|
||
|
|
return false, "", err
|
||
|
|
}
|
||
|
|
if len(list) == 0 {
|
||
|
|
return false, "", nil
|
||
|
|
}
|
||
|
|
return true, list[0].Role, nil
|
||
|
|
}
|
||
|
|
func (s *MonStore) UpsertBenchmarkSample(ctx context.Context, sample *domain.BenchmarkSample) error {
|
||
|
|
if sample.ID == "" {
|
||
|
|
sample.ID = sample.Niche + ":" + sample.OwnerHash
|
||
|
|
}
|
||
|
|
_, err := s.bench.UpdateOne(ctx, bson.M{"_id": sample.ID}, bson.M{"$set": sample}, options.Update().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
func (s *MonStore) ListBenchmarkSamples(ctx context.Context, niche string, limit int) ([]*domain.BenchmarkSample, error) {
|
||
|
|
q := bson.M{}
|
||
|
|
if niche != "" {
|
||
|
|
q["niche"] = niche
|
||
|
|
}
|
||
|
|
opts := options.Find()
|
||
|
|
if limit > 0 {
|
||
|
|
opts.SetLimit(int64(limit))
|
||
|
|
}
|
||
|
|
var list []*domain.BenchmarkSample
|
||
|
|
err := s.bench.Find(ctx, &list, q, opts)
|
||
|
|
return list, err
|
||
|
|
}
|