mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
170 lines
3.8 KiB
Go
170 lines
3.8 KiB
Go
package commit
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/eolinker/go-common/utils"
|
|
|
|
"github.com/eolinker/go-common/store"
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
var (
|
|
_ ICommitStore[any] = (*Store[any])(nil)
|
|
)
|
|
|
|
type ICommitStore[H any] interface {
|
|
Save(ctx context.Context, key string, target string, h *H) error
|
|
Latest(ctx context.Context, key string, target ...string) ([]*Commit[H], error)
|
|
Get(ctx context.Context, uuid string) (*Commit[H], error)
|
|
List(ctx context.Context, uuids ...string) ([]*Commit[H], error)
|
|
}
|
|
|
|
type Store[H any] struct {
|
|
db store.IDB `autowired:""`
|
|
latestTableName string
|
|
commitTableName string
|
|
name string
|
|
}
|
|
|
|
func (h *Store[H]) List(ctx context.Context, uuids ...string) ([]*Commit[H], error) {
|
|
if len(uuids) == 0 {
|
|
return nil, errors.New("uuids is empty")
|
|
}
|
|
db := h.db.DB(ctx).Table(h.commitTableName)
|
|
if len(uuids) == 1 {
|
|
db = db.Where("`uuid` = ?", uuids[0])
|
|
} else {
|
|
db = db.Where("`uuid` in ?", uuids)
|
|
}
|
|
|
|
var commit = make([]*Commit[H], 0, len(uuids))
|
|
err := db.Find(&commit).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return commit, nil
|
|
}
|
|
|
|
func NewCommitStore[H any](name string) *Store[H] {
|
|
return &Store[H]{
|
|
name: name,
|
|
latestTableName: name + "_latest",
|
|
commitTableName: name + "_commit",
|
|
}
|
|
}
|
|
|
|
func (h *Store[H]) OnComplete() {
|
|
|
|
onceMigrate(h.name, func() {
|
|
db := h.db.DB(context.Background())
|
|
|
|
err := db.Table(h.commitTableName).AutoMigrate(&Commit[H]{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = db.Table(h.latestTableName).AutoMigrate(&Latest{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
})
|
|
|
|
}
|
|
|
|
var (
|
|
latestUniques = []clause.Column{
|
|
{
|
|
Name: "target",
|
|
}, {
|
|
Name: "type",
|
|
},
|
|
}
|
|
)
|
|
|
|
func (h *Store[H]) Save(ctx context.Context, key string, target string, commit *H) error {
|
|
hid := uuid.NewString()
|
|
ho := &Commit[H]{
|
|
Id: 0,
|
|
UUID: hid,
|
|
Target: target,
|
|
Key: key,
|
|
Data: commit,
|
|
CreateAt: time.Now(),
|
|
}
|
|
lo := &Latest{
|
|
Id: 0,
|
|
Target: target,
|
|
Key: key,
|
|
Latest: hid,
|
|
}
|
|
|
|
return h.db.DB(ctx).Transaction(func(tx *gorm.DB) error {
|
|
err := tx.Table(h.commitTableName).Create(ho).Error
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return tx.Table(h.latestTableName).Clauses(clause.OnConflict{
|
|
Columns: latestUniques,
|
|
UpdateAll: true,
|
|
}).Create(lo).Error
|
|
|
|
})
|
|
}
|
|
func (h *Store[H]) Latest(ctx context.Context, key string, target ...string) ([]*Commit[H], error) {
|
|
|
|
wheres := make([]string, 0, 2)
|
|
args := make([]interface{}, 0, 2)
|
|
if key == "" && len(target) == 0 {
|
|
return nil, errors.New("key or target is required")
|
|
}
|
|
if key != "" {
|
|
wheres = append(wheres, "`key` = ?")
|
|
args = append(args, key)
|
|
}
|
|
if len(target) > 0 {
|
|
if len(target) > 1 {
|
|
wheres = append(wheres, "`target` in ?")
|
|
args = append(args, target)
|
|
} else {
|
|
wheres = append(wheres, "`target` = ?")
|
|
args = append(args, target[0])
|
|
}
|
|
}
|
|
|
|
latest := make([]*Latest, 0)
|
|
err := h.db.DB(ctx).Debug().Table(h.latestTableName).Where(strings.Join(wheres, " and "), args...).Find(&latest).Error
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
latestUUUID := utils.SliceToSlice(latest, func(l *Latest) string { return l.Latest })
|
|
ho := make([]*Commit[H], 0, len(latest))
|
|
if len(latestUUUID) == 0 {
|
|
return nil, nil
|
|
}
|
|
if len(latestUUUID) > 1 {
|
|
err = h.db.DB(ctx).Table(h.commitTableName).Where("`uuid` in ?", latestUUUID).Find(&ho).Error
|
|
|
|
} else {
|
|
err = h.db.DB(ctx).Table(h.commitTableName).Where("`uuid` = ?", latestUUUID[0]).Find(&ho).Error
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ho, nil
|
|
}
|
|
func (h *Store[H]) Get(ctx context.Context, uuid string) (*Commit[H], error) {
|
|
var commit = new(Commit[H])
|
|
err := h.db.DB(ctx).Table(h.commitTableName).Where("`uuid` = ?", uuid).First(commit).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return commit, nil
|
|
}
|