You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
2.9 KiB
135 lines
2.9 KiB
package mongodb
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"git.aiterp.net/rpdata/api/models"
|
|
"git.aiterp.net/rpdata/api/repositories"
|
|
"github.com/globalsign/mgo"
|
|
"github.com/globalsign/mgo/bson"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type changeRepository struct {
|
|
restoreIDs bool
|
|
changes *mgo.Collection
|
|
idCounter *counter
|
|
}
|
|
|
|
func (r *changeRepository) Find(ctx context.Context, id string) (*models.Change, error) {
|
|
change := new(models.Change)
|
|
err := r.changes.FindId(id).One(change)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return change, nil
|
|
}
|
|
|
|
func (r *changeRepository) List(ctx context.Context, filter models.ChangeFilter) ([]*models.Change, error) {
|
|
query := bson.M{}
|
|
limit := 0
|
|
if filter.EarliestDate != nil && !filter.EarliestDate.IsZero() {
|
|
query["date"] = bson.M{"$gte": *filter.EarliestDate}
|
|
}
|
|
if filter.LatestDate != nil && !filter.LatestDate.IsZero() {
|
|
dateBson, ok := query["date"].(bson.M)
|
|
if !ok {
|
|
dateBson = bson.M{}
|
|
}
|
|
|
|
dateBson["$gte"] = *filter.EarliestDate
|
|
}
|
|
if len(filter.Keys) > 0 {
|
|
query["keys"] = bson.M{"$in": filter.Keys}
|
|
} else if !r.restoreIDs {
|
|
query["listed"] = true
|
|
}
|
|
if filter.Author != nil && *filter.Author != "" {
|
|
query["author"] = *filter.Author
|
|
}
|
|
if filter.Limit != nil {
|
|
limit = *filter.Limit
|
|
}
|
|
|
|
initialSize := 64
|
|
if limit > 0 && limit < 256 {
|
|
initialSize = limit
|
|
}
|
|
|
|
changes := make([]*models.Change, 0, initialSize)
|
|
err := r.changes.Find(query).Sort("-date").Limit(limit).All(&changes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return changes, nil
|
|
}
|
|
|
|
func (r *changeRepository) Insert(ctx context.Context, change models.Change) (*models.Change, error) {
|
|
if !r.restoreIDs || change.ID == "" {
|
|
next, err := r.idCounter.Increment(1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
change.ID = "Change_" + strconv.Itoa(next)
|
|
} else {
|
|
tokens := strings.Split(change.ID, "_")
|
|
if len(tokens) != 2 || tokens[0] != "Change" {
|
|
return nil, errors.New("Invalid change ID")
|
|
}
|
|
|
|
n, err := strconv.Atoi(tokens[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
_ = r.idCounter.Bump(n)
|
|
}
|
|
|
|
err := r.changes.Insert(&change)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &change, nil
|
|
}
|
|
|
|
func (r *changeRepository) Remove(ctx context.Context, change models.Change) error {
|
|
return r.changes.RemoveId(change.ID)
|
|
}
|
|
|
|
func newChangeRepository(db *mgo.Database, restoreIDs bool) (repositories.ChangeRepository, error) {
|
|
collection := db.C("common.changes")
|
|
|
|
// Delete the old index if it exists.
|
|
_ = collection.DropIndexName("date_1")
|
|
|
|
err := collection.EnsureIndex(mgo.Index{
|
|
Name: "expiry",
|
|
Key: []string{"date"},
|
|
ExpireAfter: time.Hour * 2400, // 100 days
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = collection.EnsureIndexKey("author")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = collection.EnsureIndexKey("keys")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &changeRepository{
|
|
restoreIDs: restoreIDs,
|
|
changes: collection,
|
|
idCounter: newCounter(db, "auto_increment", "Change"),
|
|
}, nil
|
|
}
|