|
|
package mongodb
import ( "context" "errors" "git.aiterp.net/rpdata/api/internal/generate" "git.aiterp.net/rpdata/api/models" "github.com/globalsign/mgo" "github.com/globalsign/mgo/bson" "strconv" "sync" )
type logRepository struct { openMutex sync.Mutex
logs *mgo.Collection posts *mgo.Collection shortIdCounter *counter }
func newLogRepository(db *mgo.Database) (*logRepository, error) { logs := db.C("logbot3.logs") posts := db.C("logbot3.posts")
err := logs.EnsureIndexKey("date") if err != nil { return nil, err } err = logs.EnsureIndexKey("channel") if err != nil { return nil, err } err = logs.EnsureIndexKey("characterIds") if err != nil { return nil, err } err = logs.EnsureIndexKey("event") if err != nil { return nil, err } err = logs.EnsureIndex(mgo.Index{Key: []string{"channel", "open"}}) if err != nil { return nil, err }
err = logs.EnsureIndex(mgo.Index{ Key: []string{"shortId"}, Unique: true, DropDups: true, }) if err != nil { return nil, err }
return &logRepository{ logs: logs, posts: posts, shortIdCounter: newCounter(db, "auto_increment", "Log"), }, nil }
func (r *logRepository) Find(ctx context.Context, id string) (*models.Log, error) { log := new(models.Log) err := r.logs.Find(bson.M{"$or": []bson.M{{"_id": id}, {"shortId": id}}}).One(log) if err != nil { return nil, err }
return log, nil }
func (r *logRepository) List(ctx context.Context, filter models.LogFilter) ([]*models.Log, error) { query := bson.M{} if filter.Search != nil { searchQuery := bson.M{ "$text": bson.M{"$search": *filter.Search}, "logId": bson.M{"$ne": nil}, }
logIds := make([]string, 0, 64) err := r.posts.Find(searchQuery).Distinct("logId", &logIds) if err != nil { return nil, err }
query["shortId"] = bson.M{"$in": logIds} } if filter.Open != nil { r.openMutex.Lock() defer r.openMutex.Unlock()
query["open"] = filter.Open } if len(filter.Characters) > 0 { query["characterIds"] = bson.M{"$in": filter.Characters} } if len(filter.Channels) > 0 { query["channel"] = bson.M{"$in": filter.Channels} } if len(filter.Events) > 0 { query["event"] = bson.M{"$in": filter.Events} }
logs := make([]*models.Log, 0, 32) err := r.logs.Find(query).Sort("-date").Limit(filter.Limit).All(&logs) if err != nil { if err == mgo.ErrNotFound { return logs, nil }
return nil, err }
return logs, nil }
func (r *logRepository) Insert(ctx context.Context, log models.Log) (*models.Log, error) { nextShortId, err := r.shortIdCounter.Increment(1) if err != nil { return nil, err }
log.ID = generate.LogID(log) log.ShortID = "L" + strconv.Itoa(nextShortId)
if log.Open { // There can be only one open log in the same channel.
r.openMutex.Lock() defer r.openMutex.Unlock()
_, err = r.logs.UpdateAll(bson.M{"channel": log.ChannelName, "open": true}, bson.M{"$set": bson.M{"open": false}}) if err != nil { return nil, errors.New("Cannot close other logs: " + err.Error()) } }
err = r.logs.Insert(&log) if err != nil { return nil, err }
return &log, nil }
func (r *logRepository) Update(ctx context.Context, log models.Log, update models.LogUpdate) (*models.Log, error) { updateBson := bson.M{} if update.Open != nil { if *update.Open == true { // There can be only one open log in the same channel.
r.openMutex.Lock() defer r.openMutex.Unlock()
_, err := r.logs.UpdateAll(bson.M{"channel": log.ChannelName, "open": true}, bson.M{"$set": bson.M{"open": false}}) if err != nil { return nil, errors.New("Cannot close other logs: " + err.Error()) } }
updateBson["open"] = *update.Open log.Open = *update.Open } if update.Title != nil { updateBson["title"] = *update.Title log.Title = *update.Title } if update.Description != nil { updateBson["description"] = *update.Description log.Description = *update.Description } if update.EventName != nil { updateBson["event"] = *update.EventName log.EventName = *update.EventName }
err := r.logs.UpdateId(log.ID, bson.M{"$set": updateBson}) if err != nil { return nil, err }
return &log, nil }
func (r *logRepository) Delete(ctx context.Context, log models.Log) error { err := r.logs.RemoveId(log.ID) if err != nil { return err }
_, _ = r.posts.RemoveAll(bson.M{"logId": log.ShortID})
return nil }
|