056de22edb
* Feat: retrieve nodes from data table * Feat: master node ping slave node in REST API * Feat: master send scheduled ping request * Feat: inactive nodes recover loop * Modify: remove database operations from aria2 RPC caller implementation * Feat: init aria2 client in master node * Feat: Round Robin load balancer * Feat: create and monitor aria2 task in master node * Feat: salve receive and handle heartbeat * Fix: Node ID will be 0 in download record generated in older version * Feat: sign request headers with all `X-` prefix * Feat: API call to slave node will carry meta data in headers * Feat: call slave aria2 rpc method from master * Feat: get slave aria2 task status Feat: encode slave response data using gob * Feat: aria2 callback to master node / cancel or select task to slave node * Fix: use dummy aria2 client when caller initialize failed in master node * Feat: slave aria2 status event callback / salve RPC auth * Feat: prototype for slave driven filesystem * Feat: retry for init aria2 client in master node * Feat: init request client with global options * Feat: slave receive async task from master * Fix: competition write in request header * Refactor: dependency initialize order * Feat: generic message queue implementation * Feat: message queue implementation * Feat: master waiting slave transfer result * Feat: slave transfer file in stateless policy * Feat: slave transfer file in slave policy * Feat: slave transfer file in local policy * Feat: slave transfer file in OneDrive policy * Fix: failed to initialize update checker http client * Feat: list slave nodes for dashboard * Feat: test aria2 rpc connection in slave * Feat: add and save node * Feat: add and delete node in node pool * Fix: temp file cannot be removed when aria2 task fails * Fix: delete node in admin panel * Feat: edit node and get node info * Modify: delete unused settings
119 lines
2.6 KiB
Go
119 lines
2.6 KiB
Go
package task
|
||
|
||
import (
|
||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||
)
|
||
|
||
// 任务类型
|
||
const (
|
||
// CompressTaskType 压缩任务
|
||
CompressTaskType = iota
|
||
// DecompressTaskType 解压缩任务
|
||
DecompressTaskType
|
||
// TransferTaskType 中转任务
|
||
TransferTaskType
|
||
// ImportTaskType 导入任务
|
||
ImportTaskType
|
||
)
|
||
|
||
// 任务状态
|
||
const (
|
||
// Queued 排队中
|
||
Queued = iota
|
||
// Processing 处理中
|
||
Processing
|
||
// Error 失败
|
||
Error
|
||
// Canceled 取消
|
||
Canceled
|
||
// Complete 完成
|
||
Complete
|
||
)
|
||
|
||
// 任务进度
|
||
const (
|
||
// PendingProgress 等待中
|
||
PendingProgress = iota
|
||
// Compressing 压缩中
|
||
CompressingProgress
|
||
// Decompressing 解压缩中
|
||
DecompressingProgress
|
||
// Downloading 下载中
|
||
DownloadingProgress
|
||
// Transferring 转存中
|
||
TransferringProgress
|
||
// ListingProgress 索引中
|
||
ListingProgress
|
||
// InsertingProgress 插入中
|
||
InsertingProgress
|
||
)
|
||
|
||
// Job 任务接口
|
||
type Job interface {
|
||
Type() int // 返回任务类型
|
||
Creator() uint // 返回创建者ID
|
||
Props() string // 返回序列化后的任务属性
|
||
Model() *model.Task // 返回对应的数据库模型
|
||
SetStatus(int) // 设定任务状态
|
||
Do() // 开始执行任务
|
||
SetError(*JobError) // 设定任务失败信息
|
||
GetError() *JobError // 获取任务执行结果,返回nil表示成功完成执行
|
||
}
|
||
|
||
// JobError 任务失败信息
|
||
type JobError struct {
|
||
Msg string `json:"msg,omitempty"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
|
||
// Record 将任务记录到数据库中
|
||
func Record(job Job) (*model.Task, error) {
|
||
record := model.Task{
|
||
Status: Queued,
|
||
Type: job.Type(),
|
||
UserID: job.Creator(),
|
||
Progress: 0,
|
||
Error: "",
|
||
Props: job.Props(),
|
||
}
|
||
_, err := record.Create()
|
||
return &record, err
|
||
}
|
||
|
||
// Resume 从数据库中恢复未完成任务
|
||
func Resume() {
|
||
tasks := model.GetTasksByStatus(Queued, Processing)
|
||
if len(tasks) == 0 {
|
||
return
|
||
}
|
||
util.Log().Info("从数据库中恢复 %d 个未完成任务", len(tasks))
|
||
|
||
for i := 0; i < len(tasks); i++ {
|
||
job, err := GetJobFromModel(&tasks[i])
|
||
if err != nil {
|
||
util.Log().Warning("无法恢复任务,%s", err)
|
||
continue
|
||
}
|
||
|
||
if job != nil {
|
||
TaskPoll.Submit(job)
|
||
}
|
||
}
|
||
}
|
||
|
||
// GetJobFromModel 从数据库给定模型获取任务
|
||
func GetJobFromModel(task *model.Task) (Job, error) {
|
||
switch task.Type {
|
||
case CompressTaskType:
|
||
return NewCompressTaskFromModel(task)
|
||
case DecompressTaskType:
|
||
return NewDecompressTaskFromModel(task)
|
||
case TransferTaskType:
|
||
return NewTransferTaskFromModel(task)
|
||
case ImportTaskType:
|
||
return NewImportTaskFromModel(task)
|
||
default:
|
||
return nil, ErrUnknownTaskType
|
||
}
|
||
}
|