mirror of https://github.com/Xhofe/alist
				
				
				
			feat: task manager
							parent
							
								
									6d0e54d87e
								
							
						
					
					
						commit
						53e969e894
					
				| 
						 | 
					@ -7,9 +7,12 @@ import (
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/driver"
 | 
						"github.com/alist-org/alist/v3/internal/driver"
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/model"
 | 
						"github.com/alist-org/alist/v3/internal/model"
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/operations"
 | 
						"github.com/alist-org/alist/v3/internal/operations"
 | 
				
			||||||
 | 
						"github.com/alist-org/alist/v3/internal/task"
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var copyTaskManager = task.NewTaskManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CopyBetween2Accounts(ctx context.Context, srcAccount, dstAccount driver.Driver, srcPath, dstPath string) error {
 | 
					func CopyBetween2Accounts(ctx context.Context, srcAccount, dstAccount driver.Driver, srcPath, dstPath string) error {
 | 
				
			||||||
	srcFile, err := operations.Get(ctx, srcAccount, srcPath)
 | 
						srcFile, err := operations.Get(ctx, srcAccount, srcPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,12 @@ package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/driver"
 | 
						"github.com/alist-org/alist/v3/internal/driver"
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/model"
 | 
						"github.com/alist-org/alist/v3/internal/model"
 | 
				
			||||||
	"github.com/alist-org/alist/v3/internal/operations"
 | 
						"github.com/alist-org/alist/v3/internal/operations"
 | 
				
			||||||
 | 
						"github.com/alist-org/alist/v3/internal/task"
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,32 +44,25 @@ func Rename(ctx context.Context, account driver.Driver, srcPath, dstName string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Copy if in an account, call move method
 | 
					// Copy if in an account, call move method
 | 
				
			||||||
// if not, add copy task
 | 
					// if not, add copy task
 | 
				
			||||||
func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) error {
 | 
					func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) (bool, error) {
 | 
				
			||||||
	srcAccount, srcActualPath, err := operations.GetAccountAndActualPath(srcPath)
 | 
						srcAccount, srcActualPath, err := operations.GetAccountAndActualPath(srcPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.WithMessage(err, "failed get src account")
 | 
							return false, errors.WithMessage(err, "failed get src account")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dstAccount, dstActualPath, err := operations.GetAccountAndActualPath(srcPath)
 | 
						dstAccount, dstActualPath, err := operations.GetAccountAndActualPath(srcPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.WithMessage(err, "failed get dst account")
 | 
							return false, errors.WithMessage(err, "failed get dst account")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// copy if in an account, just call driver.Copy
 | 
						// copy if in an account, just call driver.Copy
 | 
				
			||||||
	if srcAccount.GetAccount() == dstAccount.GetAccount() {
 | 
						if srcAccount.GetAccount() == dstAccount.GetAccount() {
 | 
				
			||||||
		return operations.Copy(ctx, account, srcActualPath, dstActualPath)
 | 
							return false, operations.Copy(ctx, account, srcActualPath, dstActualPath)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// not in an account
 | 
						// not in an account
 | 
				
			||||||
	return CopyBetween2Accounts(ctx, srcAccount, dstAccount, srcActualPath, dstActualPath)
 | 
						// TODO add status set callback to put
 | 
				
			||||||
	// srcFile, err := operations.Get(ctx, srcAccount, srcActualPath)
 | 
						copyTaskManager.Add(fmt.Sprintf("copy %s to %s", srcActualPath, dstActualPath), func(task *task.Task) error {
 | 
				
			||||||
	// if srcFile.IsDir() {
 | 
							return CopyBetween2Accounts(context.TODO(), srcAccount, dstAccount, srcActualPath, dstActualPath)
 | 
				
			||||||
	// 	// TODO: recursive copy
 | 
						})
 | 
				
			||||||
	// 	return nil
 | 
						return true, nil
 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
	// // TODO: add copy task, maybe like this:
 | 
					 | 
				
			||||||
	// // operations.Link(ctx,srcAccount,srcActualPath,args)
 | 
					 | 
				
			||||||
	// // get a Reader from link
 | 
					 | 
				
			||||||
	// // boxing the Reader to a driver.FileStream
 | 
					 | 
				
			||||||
	// // operations.Put(ctx,dstParentPath, stream)
 | 
					 | 
				
			||||||
	// panic("TODO")
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Remove(ctx context.Context, account driver.Driver, path string) error {
 | 
					func Remove(ctx context.Context, account driver.Driver, path string) error {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					package task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"sync/atomic"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/alist-org/alist/v3/pkg/generic_sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTaskManager() *TaskManager {
 | 
				
			||||||
 | 
						return &TaskManager{
 | 
				
			||||||
 | 
							tasks: generic_sync.MapOf[int64, *Task]{},
 | 
				
			||||||
 | 
							curID: 0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskManager struct {
 | 
				
			||||||
 | 
						curID int64
 | 
				
			||||||
 | 
						tasks generic_sync.MapOf[int64, *Task]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) AddTask(task *Task) {
 | 
				
			||||||
 | 
						task.ID = tm.curID
 | 
				
			||||||
 | 
						atomic.AddInt64(&tm.curID, 1)
 | 
				
			||||||
 | 
						tm.tasks.Store(task.ID, task)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) GetAll() []*Task {
 | 
				
			||||||
 | 
						return tm.tasks.Values()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) Get(id int64) (*Task, bool) {
 | 
				
			||||||
 | 
						return tm.tasks.Load(id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) Remove(id int64) {
 | 
				
			||||||
 | 
						tm.tasks.Delete(id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) RemoveFinished() {
 | 
				
			||||||
 | 
						tasks := tm.GetAll()
 | 
				
			||||||
 | 
						for _, task := range tasks {
 | 
				
			||||||
 | 
							if task.Status == FINISHED {
 | 
				
			||||||
 | 
								tm.Remove(task.ID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) RemoveError() {
 | 
				
			||||||
 | 
						tasks := tm.GetAll()
 | 
				
			||||||
 | 
						for _, task := range tasks {
 | 
				
			||||||
 | 
							if task.Error != nil {
 | 
				
			||||||
 | 
								tm.Remove(task.ID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tm *TaskManager) Add(name string, f Func) {
 | 
				
			||||||
 | 
						task := NewTask(name, f)
 | 
				
			||||||
 | 
						tm.AddTask(task)
 | 
				
			||||||
 | 
						go task.Run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,36 @@
 | 
				
			||||||
// manage task, such as file upload, file copy between accounts, offline download, etc.
 | 
					// manage task, such as file upload, file copy between accounts, offline download, etc.
 | 
				
			||||||
package task
 | 
					package task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Func func(task *Task) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						PENDING  = "pending"
 | 
				
			||||||
 | 
						RUNNING  = "running"
 | 
				
			||||||
 | 
						FINISHED = "finished"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Task struct {
 | 
					type Task struct {
 | 
				
			||||||
	Name     string
 | 
						ID     int64
 | 
				
			||||||
	Status   string
 | 
						Name   string
 | 
				
			||||||
	Error    error
 | 
						Status string
 | 
				
			||||||
	Finish   bool
 | 
						Error  error
 | 
				
			||||||
	Children []*Task
 | 
						Func   Func
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTask(name string, func_ Func) *Task {
 | 
				
			||||||
 | 
						return &Task{
 | 
				
			||||||
 | 
							Name:   name,
 | 
				
			||||||
 | 
							Status: PENDING,
 | 
				
			||||||
 | 
							Func:   func_,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *Task) SetStatus(status string) {
 | 
				
			||||||
 | 
						t.Status = status
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *Task) Run() {
 | 
				
			||||||
 | 
						t.Status = RUNNING
 | 
				
			||||||
 | 
						t.Error = t.Func(t)
 | 
				
			||||||
 | 
						t.Status = FINISHED
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue