feat: add task info to resp of add task api (close #5579)

pull/5643/head
Andy Hsu 2023-12-03 14:44:20 +08:00
parent 8bdfc7ac8e
commit 026e944cbb
8 changed files with 79 additions and 50 deletions

View File

@ -39,23 +39,23 @@ var CopyTaskManager *tache.Manager[*CopyTask]
// Copy if in the same storage, call move method // Copy if in the same storage, call move method
// if not, add copy task // if not, add copy task
func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (bool, error) { func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (tache.TaskWithInfo, error) {
srcStorage, srcObjActualPath, err := op.GetStorageAndActualPath(srcObjPath) srcStorage, srcObjActualPath, err := op.GetStorageAndActualPath(srcObjPath)
if err != nil { if err != nil {
return false, errors.WithMessage(err, "failed get src storage") return nil, errors.WithMessage(err, "failed get src storage")
} }
dstStorage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath) dstStorage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath)
if err != nil { if err != nil {
return false, errors.WithMessage(err, "failed get dst storage") return nil, errors.WithMessage(err, "failed get dst storage")
} }
// copy if in the same storage, just call driver.Copy // copy if in the same storage, just call driver.Copy
if srcStorage.GetStorage() == dstStorage.GetStorage() { if srcStorage.GetStorage() == dstStorage.GetStorage() {
return false, op.Copy(ctx, srcStorage, srcObjActualPath, dstDirActualPath, lazyCache...) return nil, op.Copy(ctx, srcStorage, srcObjActualPath, dstDirActualPath, lazyCache...)
} }
if ctx.Value(conf.NoTaskKey) != nil { if ctx.Value(conf.NoTaskKey) != nil {
srcObj, err := op.Get(ctx, srcStorage, srcObjActualPath) srcObj, err := op.Get(ctx, srcStorage, srcObjActualPath)
if err != nil { if err != nil {
return false, errors.WithMessagef(err, "failed get src [%s] file", srcObjPath) return nil, errors.WithMessagef(err, "failed get src [%s] file", srcObjPath)
} }
if !srcObj.IsDir() { if !srcObj.IsDir() {
// copy file directly // copy file directly
@ -63,7 +63,7 @@ func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool
Header: http.Header{}, Header: http.Header{},
}) })
if err != nil { if err != nil {
return false, errors.WithMessagef(err, "failed get [%s] link", srcObjPath) return nil, errors.WithMessagef(err, "failed get [%s] link", srcObjPath)
} }
fs := stream.FileStream{ fs := stream.FileStream{
Obj: srcObj, Obj: srcObj,
@ -72,19 +72,20 @@ func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool
// any link provided is seekable // any link provided is seekable
ss, err := stream.NewSeekableStream(fs, link) ss, err := stream.NewSeekableStream(fs, link)
if err != nil { if err != nil {
return false, errors.WithMessagef(err, "failed get [%s] stream", srcObjPath) return nil, errors.WithMessagef(err, "failed get [%s] stream", srcObjPath)
} }
return false, op.Put(ctx, dstStorage, dstDirActualPath, ss, nil, false) return nil, op.Put(ctx, dstStorage, dstDirActualPath, ss, nil, false)
} }
} }
// not in the same storage // not in the same storage
CopyTaskManager.Add(&CopyTask{ t := &CopyTask{
srcStorage: srcStorage, srcStorage: srcStorage,
dstStorage: dstStorage, dstStorage: dstStorage,
srcObjPath: srcObjActualPath, srcObjPath: srcObjActualPath,
dstDirPath: dstDirActualPath, dstDirPath: dstDirActualPath,
}) }
return true, nil CopyTaskManager.Add(t)
return t, nil
} }
func copyBetween2Storages(t *CopyTask, srcStorage, dstStorage driver.Driver, srcObjPath, dstDirPath string) error { func copyBetween2Storages(t *CopyTask, srcStorage, dstStorage driver.Driver, srcObjPath, dstDirPath string) error {

View File

@ -6,6 +6,7 @@ import (
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/op"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/xhofe/tache"
) )
// the param named path of functions in this package is a mount path // the param named path of functions in this package is a mount path
@ -68,7 +69,7 @@ func Move(ctx context.Context, srcPath, dstDirPath string, lazyCache ...bool) er
return err return err
} }
func Copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (bool, error) { func Copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (tache.TaskWithInfo, error) {
res, err := _copy(ctx, srcObjPath, dstDirPath, lazyCache...) res, err := _copy(ctx, srcObjPath, dstDirPath, lazyCache...)
if err != nil { if err != nil {
log.Errorf("failed copy %s to %s: %+v", srcObjPath, dstDirPath, err) log.Errorf("failed copy %s to %s: %+v", srcObjPath, dstDirPath, err)
@ -100,12 +101,12 @@ func PutDirectly(ctx context.Context, dstDirPath string, file model.FileStreamer
return err return err
} }
func PutAsTask(dstDirPath string, file model.FileStreamer) error { func PutAsTask(dstDirPath string, file model.FileStreamer) (tache.TaskWithInfo, error) {
err := putAsTask(dstDirPath, file) t, err := putAsTask(dstDirPath, file)
if err != nil { if err != nil {
log.Errorf("failed put %s: %+v", dstDirPath, err) log.Errorf("failed put %s: %+v", dstDirPath, err)
} }
return err return t, err
} }
type GetStoragesArgs struct { type GetStoragesArgs struct {

View File

@ -33,28 +33,29 @@ func (t *UploadTask) Run() error {
var UploadTaskManager *tache.Manager[*UploadTask] var UploadTaskManager *tache.Manager[*UploadTask]
// putAsTask add as a put task and return immediately // putAsTask add as a put task and return immediately
func putAsTask(dstDirPath string, file model.FileStreamer) error { func putAsTask(dstDirPath string, file model.FileStreamer) (tache.TaskWithInfo, error) {
storage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath) storage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath)
if err != nil { if err != nil {
return errors.WithMessage(err, "failed get storage") return nil, errors.WithMessage(err, "failed get storage")
} }
if storage.Config().NoUpload { if storage.Config().NoUpload {
return errors.WithStack(errs.UploadNotSupported) return nil, errors.WithStack(errs.UploadNotSupported)
} }
if file.NeedStore() { if file.NeedStore() {
_, err := file.CacheFullInTempFile() _, err := file.CacheFullInTempFile()
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to create temp file") return nil, errors.Wrapf(err, "failed to create temp file")
} }
//file.SetReader(tempFile) //file.SetReader(tempFile)
//file.SetTmpFile(tempFile) //file.SetTmpFile(tempFile)
} }
UploadTaskManager.Add(&UploadTask{ t := &UploadTask{
storage: storage, storage: storage,
dstDirActualPath: dstDirActualPath, dstDirActualPath: dstDirActualPath,
file: file, file: file,
}) }
return nil UploadTaskManager.Add(t)
return t, nil
} }
// putDirect put the file and return after finish // putDirect put the file and return after finish

View File

@ -7,6 +7,7 @@ import (
"github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/op"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/xhofe/tache"
"path/filepath" "path/filepath"
) )
@ -26,38 +27,38 @@ type AddURLArgs struct {
DeletePolicy DeletePolicy DeletePolicy DeletePolicy
} }
func AddURL(ctx context.Context, args *AddURLArgs) error { func AddURL(ctx context.Context, args *AddURLArgs) (tache.TaskWithInfo, error) {
// get tool // get tool
tool, err := Tools.Get(args.Tool) tool, err := Tools.Get(args.Tool)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed get tool") return nil, errors.Wrapf(err, "failed get tool")
} }
// check tool is ready // check tool is ready
if !tool.IsReady() { if !tool.IsReady() {
// try to init tool // try to init tool
if _, err := tool.Init(); err != nil { if _, err := tool.Init(); err != nil {
return errors.Wrapf(err, "failed init tool %s", args.Tool) return nil, errors.Wrapf(err, "failed init tool %s", args.Tool)
} }
} }
// check storage // check storage
storage, dstDirActualPath, err := op.GetStorageAndActualPath(args.DstDirPath) storage, dstDirActualPath, err := op.GetStorageAndActualPath(args.DstDirPath)
if err != nil { if err != nil {
return errors.WithMessage(err, "failed get storage") return nil, errors.WithMessage(err, "failed get storage")
} }
// check is it could upload // check is it could upload
if storage.Config().NoUpload { if storage.Config().NoUpload {
return errors.WithStack(errs.UploadNotSupported) return nil, errors.WithStack(errs.UploadNotSupported)
} }
// check path is valid // check path is valid
obj, err := op.Get(ctx, storage, dstDirActualPath) obj, err := op.Get(ctx, storage, dstDirActualPath)
if err != nil { if err != nil {
if !errs.IsObjectNotFound(err) { if !errs.IsObjectNotFound(err) {
return errors.WithMessage(err, "failed get object") return nil, errors.WithMessage(err, "failed get object")
} }
} else { } else {
if !obj.IsDir() { if !obj.IsDir() {
// can't add to a file // can't add to a file
return errors.WithStack(errs.NotFolder) return nil, errors.WithStack(errs.NotFolder)
} }
} }
@ -71,5 +72,5 @@ func AddURL(ctx context.Context, args *AddURLArgs) error {
tool: tool, tool: tool,
} }
DownloadTaskManager.Add(t) DownloadTaskManager.Add(t)
return nil return t, nil
} }

View File

@ -2,6 +2,7 @@ package handles
import ( import (
"fmt" "fmt"
"github.com/xhofe/tache"
"io" "io"
stdpath "path" stdpath "path"
@ -120,22 +121,20 @@ func FsCopy(c *gin.Context) {
common.ErrorResp(c, err, 403) common.ErrorResp(c, err, 403)
return return
} }
var addedTask []string var addedTasks []tache.TaskWithInfo
for i, name := range req.Names { for i, name := range req.Names {
ok, err := fs.Copy(c, stdpath.Join(srcDir, name), dstDir, len(req.Names) > i+1) t, err := fs.Copy(c, stdpath.Join(srcDir, name), dstDir, len(req.Names) > i+1)
if ok { if t != nil {
addedTask = append(addedTask, name) addedTasks = append(addedTasks, t)
} }
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
} }
if len(addedTask) > 0 { common.SuccessResp(c, gin.H{
common.SuccessResp(c, fmt.Sprintf("Added %d tasks", len(addedTask))) "tasks": getTaskInfos(addedTasks),
} else { })
common.SuccessResp(c)
}
} }
type RenameReq struct { type RenameReq struct {

View File

@ -1,6 +1,7 @@
package handles package handles
import ( import (
"github.com/xhofe/tache"
"io" "io"
"net/url" "net/url"
stdpath "path" stdpath "path"
@ -57,8 +58,9 @@ func FsStream(c *gin.Context) {
Mimetype: c.GetHeader("Content-Type"), Mimetype: c.GetHeader("Content-Type"),
WebPutAsTask: asTask, WebPutAsTask: asTask,
} }
var t tache.TaskWithInfo
if asTask { if asTask {
err = fs.PutAsTask(dir, s) t, err = fs.PutAsTask(dir, s)
} else { } else {
err = fs.PutDirectly(c, dir, s, true) err = fs.PutDirectly(c, dir, s, true)
} }
@ -67,7 +69,13 @@ func FsStream(c *gin.Context) {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
common.SuccessResp(c) if t == nil {
common.SuccessResp(c)
return
}
common.SuccessResp(c, gin.H{
"task": getTaskInfo(t),
})
} }
func FsForm(c *gin.Context) { func FsForm(c *gin.Context) {
@ -115,11 +123,12 @@ func FsForm(c *gin.Context) {
Mimetype: file.Header.Get("Content-Type"), Mimetype: file.Header.Get("Content-Type"),
WebPutAsTask: asTask, WebPutAsTask: asTask,
} }
var t tache.TaskWithInfo
if asTask { if asTask {
s.Reader = struct { s.Reader = struct {
io.Reader io.Reader
}{f} }{f}
err = fs.PutAsTask(dir, &s) t, err = fs.PutAsTask(dir, &s)
} else { } else {
ss, err := stream.NewSeekableStream(s, nil) ss, err := stream.NewSeekableStream(s, nil)
if err != nil { if err != nil {
@ -132,5 +141,11 @@ func FsForm(c *gin.Context) {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
common.SuccessResp(c) if t == nil {
common.SuccessResp(c)
return
}
common.SuccessResp(c, gin.H{
"task": getTaskInfo(t),
})
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/server/common" "github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/xhofe/tache"
) )
type SetAria2Req struct { type SetAria2Req struct {
@ -97,8 +98,9 @@ func AddOfflineDownload(c *gin.Context) {
common.ErrorResp(c, err, 403) common.ErrorResp(c, err, 403)
return return
} }
var tasks []tache.TaskWithInfo
for _, url := range req.Urls { for _, url := range req.Urls {
err := tool.AddURL(c, &tool.AddURLArgs{ t, err := tool.AddURL(c, &tool.AddURLArgs{
URL: url, URL: url,
DstDirPath: reqPath, DstDirPath: reqPath,
Tool: req.Tool, Tool: req.Tool,
@ -108,6 +110,9 @@ func AddOfflineDownload(c *gin.Context) {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
tasks = append(tasks, t)
} }
common.SuccessResp(c) common.SuccessResp(c, gin.H{
"tasks": getTaskInfos(tasks),
})
} }

View File

@ -3,6 +3,7 @@ package handles
import ( import (
"github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/offline_download/tool" "github.com/alist-org/alist/v3/internal/offline_download/tool"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server/common" "github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/xhofe/tache" "github.com/xhofe/tache"
@ -33,11 +34,7 @@ func getTaskInfo[T tache.TaskWithInfo](task T) TaskInfo {
} }
func getTaskInfos[T tache.TaskWithInfo](tasks []T) []TaskInfo { func getTaskInfos[T tache.TaskWithInfo](tasks []T) []TaskInfo {
var infos []TaskInfo return utils.MustSliceConvert(tasks, getTaskInfo[T])
for _, t := range tasks {
infos = append(infos, getTaskInfo(t))
}
return infos
} }
func taskRoute[T tache.TaskWithInfo](g *gin.RouterGroup, manager *tache.Manager[T]) { func taskRoute[T tache.TaskWithInfo](g *gin.RouterGroup, manager *tache.Manager[T]) {
@ -48,6 +45,15 @@ func taskRoute[T tache.TaskWithInfo](g *gin.RouterGroup, manager *tache.Manager[
g.GET("/done", func(c *gin.Context) { g.GET("/done", func(c *gin.Context) {
common.SuccessResp(c, getTaskInfos(manager.GetByState(tache.StateCanceled, tache.StateFailed, tache.StateSucceeded))) common.SuccessResp(c, getTaskInfos(manager.GetByState(tache.StateCanceled, tache.StateFailed, tache.StateSucceeded)))
}) })
g.POST("/info", func(c *gin.Context) {
tid := c.Query("tid")
task, ok := manager.GetByID(tid)
if !ok {
common.ErrorStrResp(c, "task not found", 404)
return
}
common.SuccessResp(c, getTaskInfo(task))
})
g.POST("/cancel", func(c *gin.Context) { g.POST("/cancel", func(c *gin.Context) {
tid := c.Query("tid") tid := c.Query("tid")
manager.Cancel(tid) manager.Cancel(tid)