perf: optimize batch task creation with single transaction
批量创建任务使用单事务数据库插入,显著提升性能。 移除任务列表的批量取消/删除进度显示(批处理接口无意义)。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+67
-30
@@ -7,6 +7,7 @@ import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"bilidown/internal/task"
|
||||
"bilidown/internal/util"
|
||||
@@ -24,54 +25,90 @@ func createTask(w http.ResponseWriter, r *http.Request) {
|
||||
util.Res{Success: false, Message: "参数错误"}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
if len(body) == 0 {
|
||||
util.Res{Success: false, Message: "任务列表为空"}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
db := util.MustGetDB()
|
||||
defer db.Close()
|
||||
|
||||
// 预先获取下载目录,避免循环中重复查询
|
||||
// 预先获取下载目录
|
||||
folder, err := util.GetCurrentFolder(db)
|
||||
if err != nil {
|
||||
util.Res{Success: false, Message: fmt.Sprintf("获取下载目录失败: %v", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 批量验证参数
|
||||
for _, item := range body {
|
||||
if !util.CheckBvidFormat(item.Bvid) {
|
||||
util.Res{Success: false, Message: "bvid 格式错误"}.Write(w)
|
||||
util.Res{Success: false, Message: fmt.Sprintf("bvid 格式错误: %s", item.Bvid)}.Write(w)
|
||||
return
|
||||
}
|
||||
if item.Cover == "" || item.Title == "" || item.Owner == "" {
|
||||
util.Res{Success: false, Message: "参数错误"}.Write(w)
|
||||
if item.Title == "" || item.Owner == "" {
|
||||
util.Res{Success: false, Message: "标题或作者为空"}.Write(w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 批量数据库插入(单事务)
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
util.Res{Success: false, Message: fmt.Sprintf("开启事务失败: %v", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`INSERT INTO "task" ("bvid", "cid", "format", "title", "owner", "cover", "status", "folder", "duration", "download_type")
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
util.Res{Success: false, Message: fmt.Sprintf("准备语句失败: %v", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
tasks := make([]*task.Task, 0, len(body))
|
||||
for _, item := range body {
|
||||
item.Folder = folder
|
||||
item.Status = "waiting"
|
||||
item.Title = util.FilterFileName(item.Title)
|
||||
_task := task.Task{TaskInDB: item}
|
||||
|
||||
util.SqliteLock.Lock()
|
||||
result, err := stmt.Exec(
|
||||
item.Bvid, item.Cid, item.Format, item.Title, item.Owner,
|
||||
item.Cover, item.Status, item.Folder, item.Duration, item.DownloadType,
|
||||
)
|
||||
util.SqliteLock.Unlock()
|
||||
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
util.Res{Success: false, Message: fmt.Sprintf("插入任务失败: %v", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
if !util.IsValidURL(item.Cover) {
|
||||
util.Res{Success: false, Message: "封面链接格式错误"}.Write(w)
|
||||
return
|
||||
}
|
||||
if !util.IsValidURL(item.Audio) {
|
||||
util.Res{Success: false, Message: "音频链接格式错误"}.Write(w)
|
||||
return
|
||||
}
|
||||
if !util.IsValidURL(item.Video) {
|
||||
util.Res{Success: false, Message: "视频链接格式错误"}.Write(w)
|
||||
return
|
||||
}
|
||||
if !util.IsValidFormatCode(item.Format) {
|
||||
util.Res{Success: false, Message: "清晰度代码错误"}.Write(w)
|
||||
return
|
||||
}
|
||||
item.Folder = folder
|
||||
item.Status = "waiting"
|
||||
_task := task.Task{TaskInDB: item}
|
||||
_task.Title = util.FilterFileName(_task.Title)
|
||||
err = _task.Create(db)
|
||||
if err != nil {
|
||||
util.Res{Success: false, Message: fmt.Sprintf("_task.Create: %v.", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
_task.ID, _ = result.LastInsertId()
|
||||
_task.CreateAt = time.Now()
|
||||
tasks = append(tasks, &_task)
|
||||
}
|
||||
|
||||
util.SqliteLock.Lock()
|
||||
err = tx.Commit()
|
||||
util.SqliteLock.Unlock()
|
||||
|
||||
if err != nil {
|
||||
util.Res{Success: false, Message: fmt.Sprintf("提交事务失败: %v", err)}.Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 批量启动下载任务
|
||||
for _, _task := range tasks {
|
||||
go _task.Start()
|
||||
}
|
||||
util.Res{Success: true, Message: "创建成功"}.Write(w)
|
||||
|
||||
util.Res{Success: true, Message: fmt.Sprintf("成功创建 %d 个任务", len(tasks))}.Write(w)
|
||||
}
|
||||
|
||||
func getActiveTask(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user