feat: job list

This commit is contained in:
Samuel N Cui
2023-08-29 18:02:57 +08:00
parent cda9244e8e
commit 852cf8212e
80 changed files with 6173 additions and 1854 deletions

View File

@@ -1,6 +1,13 @@
package library
import (
"context"
"encoding/json"
"fmt"
"github.com/abc950309/tapewriter/entity"
"github.com/modern-go/reflect2"
"github.com/samber/lo"
"gorm.io/gorm"
)
@@ -19,3 +26,94 @@ func New(db *gorm.DB) *Library {
func (l *Library) AutoMigrate() error {
return l.db.AutoMigrate(ModelFile, ModelPosition, ModelTape)
}
type ExportLibrary struct {
Files *[]*File `json:"files,omitempty"`
Tapes *[]*Tape `json:"tapes,omitempty"`
Positions *[]*Position `json:"positions,omitempty"`
}
func (l *Library) Export(ctx context.Context, types []entity.LibraryEntityType) ([]byte, error) {
results := new(ExportLibrary)
for _, t := range lo.Uniq(types) {
switch t {
case entity.LibraryEntityType_FILE:
files, err := listAll(ctx, l, make([]*File, 0, batchSize))
if err != nil {
return nil, fmt.Errorf("list all files fail, %w", err)
}
results.Files = &files
case entity.LibraryEntityType_TAPE:
tapes, err := listAll(ctx, l, make([]*Tape, 0, batchSize))
if err != nil {
return nil, fmt.Errorf("list all tapes fail, %w", err)
}
results.Tapes = &tapes
case entity.LibraryEntityType_POSITION:
positions, err := listAll(ctx, l, make([]*Position, 0, batchSize))
if err != nil {
return nil, fmt.Errorf("list all positions fail, %w", err)
}
results.Positions = &positions
}
}
return json.Marshal(results)
}
func (l *Library) Import(ctx context.Context, buf []byte) error {
results := new(ExportLibrary)
if err := json.Unmarshal(buf, results); err != nil {
return fmt.Errorf("unmarshal import data fail, %w", err)
}
if results.Files != nil {
if r := l.db.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(ModelFile); r.Error != nil {
return fmt.Errorf("cleanup file fail, %w", r.Error)
}
if r := l.db.WithContext(ctx).CreateInBatches(*results.Files, 100); r.Error != nil {
return fmt.Errorf("insert file fail, %w", r.Error)
}
}
if results.Tapes != nil {
if r := l.db.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(ModelTape); r.Error != nil {
return fmt.Errorf("cleanup tape fail, %w", r.Error)
}
if r := l.db.WithContext(ctx).CreateInBatches(*results.Tapes, 100); r.Error != nil {
return fmt.Errorf("insert tape fail, %w", r.Error)
}
}
if results.Positions != nil {
if r := l.db.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(ModelPosition); r.Error != nil {
return fmt.Errorf("cleanup position fail, %w", r.Error)
}
if r := l.db.WithContext(ctx).CreateInBatches(*results.Positions, 100); r.Error != nil {
return fmt.Errorf("insert position fail, %w", r.Error)
}
}
return nil
}
func listAll[T any](ctx context.Context, l *Library, items []T) ([]T, error) {
v := new(T)
id := reflect2.TypeOfPtr(*v).Elem().(reflect2.StructType).FieldByName("ID")
var cursor int64
for {
batch := make([]T, 0, batchSize)
if r := l.db.WithContext(ctx).Where("id > ?", cursor).Order("id ASC").Limit(batchSize).Find(&batch); r.Error != nil {
return nil, fmt.Errorf("list files fail, cursor= %d, %w", cursor, r.Error)
}
if len(batch) == 0 {
return items, nil
}
c := id.Get(batch[len(batch)-1]).(*int64)
cursor = *c
items = append(items, batch...)
}
}

View File

@@ -4,8 +4,6 @@ import (
"context"
"fmt"
"time"
"gorm.io/gorm"
)
var (
@@ -26,20 +24,20 @@ type Position struct {
}
func (l *Library) GetPositionByFileID(ctx context.Context, fileID int64) ([]*Position, error) {
results, err := l.MGetPositionByFileID(ctx, l.db.WithContext(ctx), fileID)
results, err := l.MGetPositionByFileID(ctx, fileID)
if err != nil {
panic(err)
}
return results[fileID], nil
}
func (l *Library) MGetPositionByFileID(ctx context.Context, tx *gorm.DB, fileIDs ...int64) (map[int64][]*Position, error) {
func (l *Library) MGetPositionByFileID(ctx context.Context, fileIDs ...int64) (map[int64][]*Position, error) {
if len(fileIDs) == 0 {
return map[int64][]*Position{}, nil
}
positions := make([]*Position, 0, len(fileIDs))
if r := tx.Where("file_id IN (?)", fileIDs).Find(&positions); r.Error != nil {
if r := l.db.WithContext(ctx).Where("file_id IN (?)", fileIDs).Find(&positions); r.Error != nil {
return nil, fmt.Errorf("find position by file id fail, %w", r.Error)
}

View File

@@ -5,6 +5,8 @@ import (
"fmt"
"os"
"time"
"github.com/abc950309/tapewriter/entity"
)
var (
@@ -78,6 +80,35 @@ func (l *Library) GetTape(ctx context.Context, id int64) (*Tape, error) {
return tape, nil
}
func (l *Library) DeleteTapes(ctx context.Context, ids ...int64) error {
if r := l.db.WithContext(ctx).Where("id IN (?)", ids).Delete(ModelTape); r.Error != nil {
return fmt.Errorf("delete tapes fail, err= %w", r.Error)
}
return nil
}
func (l *Library) ListTape(ctx context.Context, filter *entity.TapeFilter) ([]*Tape, error) {
db := l.db.WithContext(ctx)
if filter.Limit != nil {
db = db.Limit(int(*filter.Limit))
} else {
db = db.Limit(20)
}
if filter.Offset != nil {
db = db.Offset(int(*filter.Offset))
}
db = db.Order("create_time DESC")
tapes := make([]*Tape, 0, 20)
if r := db.Find(&tapes); r.Error != nil {
return nil, fmt.Errorf("list tapes fail, err= %w", r.Error)
}
return tapes, nil
}
func (l *Library) MGetTape(ctx context.Context, tapeIDs ...int64) (map[int64]*Tape, error) {
if len(tapeIDs) == 0 {
return map[int64]*Tape{}, nil