Fix: aria2 RPC retry / return NoT_FOUND error while listing not existed path
This commit is contained in:
parent
7a6c84a115
commit
f235ad1def
11 changed files with 125 additions and 16 deletions
|
@ -29,6 +29,7 @@ type Download struct {
|
|||
|
||||
// 数据库忽略字段
|
||||
StatusInfo rpc.StatusInfo `gorm:"-"`
|
||||
Task *Task `gorm:"-"`
|
||||
}
|
||||
|
||||
// AfterFind 找到下载任务后的钩子,处理Status结构
|
||||
|
@ -38,6 +39,10 @@ func (task *Download) AfterFind() (err error) {
|
|||
err = json.Unmarshal([]byte(task.Attrs), &task.StatusInfo)
|
||||
}
|
||||
|
||||
if task.TaskID != 0 {
|
||||
task.Task, _ = GetTasksByID(task.TaskID)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -72,10 +77,15 @@ func GetDownloadsByStatus(status ...int) []Download {
|
|||
}
|
||||
|
||||
// GetDownloadsByStatusAndUser 根据状态检索和用户ID下载
|
||||
// page 为 0 表示列出所有,非零时分页
|
||||
// TODO 测试
|
||||
func GetDownloadsByStatusAndUser(uid uint, status ...int) []Download {
|
||||
func GetDownloadsByStatusAndUser(page, uid uint, status ...int) []Download {
|
||||
var tasks []Download
|
||||
DB.Where("user_id = ? and status in (?)", uid, status).Find(&tasks)
|
||||
dbChain := DB
|
||||
if page > 0 {
|
||||
dbChain = dbChain.Limit(10).Offset((page - 1) * 10).Order("updated_at DESC")
|
||||
}
|
||||
dbChain.Where("user_id = ? and status in (?)", uid, status).Find(&tasks)
|
||||
return tasks
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,16 @@ func (task *Task) SetError(err string) error {
|
|||
}
|
||||
|
||||
// GetTasksByStatus 根据状态检索任务
|
||||
func GetTasksByStatus(status int) []Task {
|
||||
func GetTasksByStatus(status ...int) []Task {
|
||||
var tasks []Task
|
||||
DB.Where("status = ?", status).Find(&tasks)
|
||||
DB.Where("status in (?)", status).Find(&tasks)
|
||||
return tasks
|
||||
}
|
||||
|
||||
// GetTasksByID 根据ID检索任务
|
||||
// TODO 测试
|
||||
func GetTasksByID(id interface{}) (*Task, error) {
|
||||
task := &Task{}
|
||||
result := DB.Where("id = ?", id).First(task)
|
||||
return task, result.Error
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ type Monitor struct {
|
|||
Interval time.Duration
|
||||
|
||||
notifier chan StatusEvent
|
||||
retried int
|
||||
}
|
||||
|
||||
// StatusEvent 状态改变事件
|
||||
|
@ -68,11 +69,20 @@ func (monitor *Monitor) Loop() {
|
|||
func (monitor *Monitor) Update() bool {
|
||||
status, err := Instance.Status(monitor.Task)
|
||||
if err != nil {
|
||||
monitor.retried++
|
||||
util.Log().Warning("无法获取下载任务[%s]的状态,%s", monitor.Task.GID, err)
|
||||
monitor.setErrorStatus(err)
|
||||
monitor.RemoveTempFolder()
|
||||
return true
|
||||
|
||||
// 十次重试后认定为任务失败
|
||||
if monitor.retried > 10 {
|
||||
util.Log().Warning("无法获取下载任务[%s]的状态,超过最大重试次数限制,%s", monitor.Task.GID, err)
|
||||
monitor.setErrorStatus(err)
|
||||
monitor.RemoveTempFolder()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
monitor.retried = 0
|
||||
|
||||
// 磁力链下载需要跟随
|
||||
if len(status.FollowedBy) > 0 {
|
||||
|
|
|
@ -253,9 +253,8 @@ func (fs *FileSystem) ListDeleteFiles(ctx context.Context, ids []uint) error {
|
|||
func (fs *FileSystem) List(ctx context.Context, dirPath string, pathProcessor func(string) string) ([]Object, error) {
|
||||
// 获取父目录
|
||||
isExist, folder := fs.IsPathExist(dirPath)
|
||||
// 不存在时返回空的结果
|
||||
if !isExist {
|
||||
return []Object{}, nil
|
||||
return nil, ErrPathNotExist
|
||||
}
|
||||
fs.SetTargetDir(&[]model.Folder{*folder})
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ type DownloadListResponse struct {
|
|||
UpdateInterval int `json:"interval"`
|
||||
Name string `json:"name"`
|
||||
Status int `json:"status"`
|
||||
UserID uint `json:"uid"`
|
||||
Error string `json:"error"`
|
||||
Dst string `json:"dst"`
|
||||
Total uint64 `json:"total"`
|
||||
Downloaded uint64 `json:"downloaded"`
|
||||
|
@ -21,6 +19,58 @@ type DownloadListResponse struct {
|
|||
Info rpc.StatusInfo `json:"info"`
|
||||
}
|
||||
|
||||
// FinishedListResponse 已完成任务条目
|
||||
type FinishedListResponse struct {
|
||||
Name string `json:"name"`
|
||||
Status int `json:"status"`
|
||||
Dst string `json:"dst"`
|
||||
Error string `json:"error"`
|
||||
Total uint64 `json:"total"`
|
||||
Files []rpc.FileInfo `json:"files"`
|
||||
TaskStatus int `json:"task_status"`
|
||||
TaskError string `json:"task_error"`
|
||||
CreateTime string `json:"create"`
|
||||
UpdateTime string `json:"update"`
|
||||
}
|
||||
|
||||
// BuildFinishedListResponse 构建已完成任务条目
|
||||
func BuildFinishedListResponse(tasks []model.Download) Response {
|
||||
resp := make([]FinishedListResponse, 0, len(tasks))
|
||||
|
||||
for i := 0; i < len(tasks); i++ {
|
||||
fileName := tasks[i].StatusInfo.BitTorrent.Info.Name
|
||||
if len(tasks[i].StatusInfo.Files) == 1 {
|
||||
fileName = path.Base(tasks[i].StatusInfo.Files[0].Path)
|
||||
}
|
||||
|
||||
// 过滤敏感信息
|
||||
for i2 := 0; i2 < len(tasks[i].StatusInfo.Files); i2++ {
|
||||
tasks[i].StatusInfo.Files[i2].Path = path.Base(tasks[i].StatusInfo.Files[i2].Path)
|
||||
}
|
||||
|
||||
download := FinishedListResponse{
|
||||
Name: fileName,
|
||||
Status: tasks[i].Status,
|
||||
Error: tasks[i].Error,
|
||||
Dst: tasks[i].Dst,
|
||||
Total: tasks[i].TotalSize,
|
||||
Files: tasks[i].StatusInfo.Files,
|
||||
TaskStatus: -1,
|
||||
UpdateTime: tasks[i].UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
CreateTime: tasks[i].CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
if tasks[i].Task != nil {
|
||||
download.TaskError = tasks[i].Task.Error
|
||||
download.TaskStatus = tasks[i].Task.Status
|
||||
}
|
||||
|
||||
resp = append(resp, download)
|
||||
}
|
||||
|
||||
return Response{Data: resp}
|
||||
}
|
||||
|
||||
// BuildDownloadingResponse 构建正在下载的列表响应
|
||||
func BuildDownloadingResponse(tasks []model.Download) Response {
|
||||
resp := make([]DownloadListResponse, 0, len(tasks))
|
||||
|
@ -43,8 +93,6 @@ func BuildDownloadingResponse(tasks []model.Download) Response {
|
|||
UpdateInterval: interval,
|
||||
Name: fileName,
|
||||
Status: tasks[i].Status,
|
||||
UserID: tasks[i].UserID,
|
||||
Error: tasks[i].Error,
|
||||
Dst: tasks[i].Dst,
|
||||
Total: tasks[i].TotalSize,
|
||||
Downloaded: tasks[i].DownloadedSize,
|
||||
|
|
|
@ -77,7 +77,7 @@ func Record(job Job) (*model.Task, error) {
|
|||
|
||||
// Resume 从数据库中恢复未完成任务
|
||||
func Resume() {
|
||||
tasks := model.GetTasksByStatus(Queued)
|
||||
tasks := model.GetTasksByStatus(Queued, Processing)
|
||||
if len(tasks) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -92,3 +92,14 @@ func ListDownloading(c *gin.Context) {
|
|||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
||||
// ListFinished 获取已完成的任务
|
||||
func ListFinished(c *gin.Context) {
|
||||
var service aria2.DownloadListService
|
||||
if err := c.ShouldBindQuery(&service); err == nil {
|
||||
res := service.Finished(c, CurrentUser(c))
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,3 +341,14 @@ func GetUploadCredential(c *gin.Context) {
|
|||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
||||
// SearchFile 搜索文件
|
||||
func SearchFile(c *gin.Context) {
|
||||
var service explorer.ItemDecompressService
|
||||
if err := c.ShouldBindJSON(&service); err == nil {
|
||||
res := service.CreateDecompressTask(c)
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,6 +271,8 @@ func InitMasterRouter() *gin.Engine {
|
|||
file.POST("compress", controllers.Compress)
|
||||
// 创建文件解压缩任务
|
||||
file.POST("decompress", controllers.Decompress)
|
||||
// 创建文件解压缩任务
|
||||
file.GET("search/:type/:keywords", controllers.SearchFile)
|
||||
}
|
||||
|
||||
// 离线下载任务
|
||||
|
@ -286,6 +288,8 @@ func InitMasterRouter() *gin.Engine {
|
|||
aria2.DELETE("task/:gid", controllers.CancelAria2Download)
|
||||
// 获取正在下载中的任务
|
||||
aria2.GET("downloading", controllers.ListDownloading)
|
||||
// 获取已完成的任务
|
||||
aria2.GET("finished", controllers.ListFinished)
|
||||
}
|
||||
|
||||
// 目录
|
||||
|
|
|
@ -19,12 +19,20 @@ type DownloadTaskService struct {
|
|||
|
||||
// DownloadListService 下载列表服务
|
||||
type DownloadListService struct {
|
||||
Page uint `form:"page"`
|
||||
}
|
||||
|
||||
// Finished 获取已完成的任务
|
||||
func (service *DownloadListService) Finished(c *gin.Context, user *model.User) serializer.Response {
|
||||
// 查找下载记录
|
||||
downloads := model.GetDownloadsByStatusAndUser(service.Page, user.ID, aria2.Error, aria2.Complete, aria2.Canceled, aria2.Unknown)
|
||||
return serializer.BuildFinishedListResponse(downloads)
|
||||
}
|
||||
|
||||
// Downloading 获取正在下载中的任务
|
||||
func (service *DownloadListService) Downloading(c *gin.Context, user *model.User) serializer.Response {
|
||||
// 查找下载记录
|
||||
downloads := model.GetDownloadsByStatusAndUser(user.ID, aria2.Downloading, aria2.Paused, aria2.Ready)
|
||||
downloads := model.GetDownloadsByStatusAndUser(service.Page, user.ID, aria2.Downloading, aria2.Paused, aria2.Ready)
|
||||
return serializer.BuildDownloadingResponse(downloads)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func (service *DirectoryService) ListDirectory(c *gin.Context) serializer.Respon
|
|||
// 获取子项目
|
||||
objects, err := fs.List(ctx, service.Path, nil)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeCreateFolderFailed, err.Error(), err)
|
||||
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
||||
}
|
||||
|
||||
var parentID uint
|
||||
|
|
Loading…
Add table
Reference in a new issue