refactor(core): 任务与模型协议治理 - 拆分服务职责并禁止已发起任务取消

This commit is contained in:
ddCat committed 2026-08-22 09:52:09 +08:00
1 parent 7418ddfa9c
commit 633560a5d8
91 files changed
+6380 -4247

No files matched your search

+59 -2
View File
@@ -27,6 +27,8 @@ var ErrTextReplayClosed = errors.New("text replay task is closed")
var ErrProjectAssetFolderNotEmpty = errors.New("project asset folder is not empty")
var ErrProjectHasActiveTasks = errors.New("project has active tasks")
type Repository struct {
db *gorm.DB
}
@@ -322,6 +324,17 @@ func (r *Repository) ActiveTaskCountForUser(userID string) (int64, error) {
return count, err
}
func (r *Repository) ActiveTaskCountForProjectIDs(userID string, projectIDs []string) (int64, error) {
if len(projectIDs) == 0 {
return 0, nil
}
var count int64
err := r.db.Model(&model.Task{}).
Where("user_id = ? AND project_id IN ? AND status IN ?", userID, projectIDs, []model.TaskStatus{model.TaskStatusQueued, model.TaskStatusRunning}).
Count(&count).Error
return count, err
}
// 任务领取以数据库租约为真相;PostgreSQL 锁行跳过竞争任务,SQLite 继续依赖条件更新保证单实例原子性。
func (r *Repository) ClaimNextTask(owner string, leaseDuration time.Duration) (*model.Task, error) {
var task model.Task
@@ -854,6 +867,10 @@ func (r *Repository) SaveResource(resource *model.Resource) error {
return r.db.Save(resource).Error
}
func (r *Repository) DeleteResource(userID string, id string) error {
return r.db.Delete(&model.Resource{}, "id = ? AND user_id = ?", id, userID).Error
}
func (r *Repository) Resource(id string) (*model.Resource, error) {
var resource model.Resource
if err := r.db.First(&resource, "id = ?", id).Error; err != nil {
@@ -985,14 +1002,48 @@ func (r *Repository) UpdateProject(project *model.Project) error {
}).Error
}
func (r *Repository) DeleteProject(userID string, id string) error {
func (r *Repository) DeleteProject(userID string, id string, canvasUpdates []model.CanvasProject) error {
return r.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&model.CanvasProject{}).Where("user_id = ? AND project_id = ?", userID, id).Update("project_id", "").Error; err != nil {
var canvasIDs []string
if err := tx.Model(&model.CanvasProject{}).
Where("user_id = ? AND project_id = ?", userID, id).
Pluck("id", &canvasIDs).Error; err != nil {
return err
}
projectScopeIDs := append([]string{id}, canvasIDs...)
var activeTaskCount int64
if err := tx.Model(&model.Task{}).
Where("user_id = ? AND project_id IN ? AND status IN ?", userID, projectScopeIDs, []model.TaskStatus{model.TaskStatusQueued, model.TaskStatusRunning}).
Count(&activeTaskCount).Error; err != nil {
return err
}
if activeTaskCount > 0 {
return ErrProjectHasActiveTasks
}
if err := tx.Where("user_id = ? AND project_id = ?", userID, id).Delete(&model.CanvasShare{}).Error; err != nil {
return err
}
if err := tx.Where("project_id = ?", id).Delete(&model.CanvasUnitLink{}).Error; err != nil {
return err
}
for _, canvas := range canvasUpdates {
result := tx.Model(&model.CanvasProject{}).
Where("id = ? AND user_id = ? AND project_id = ?", canvas.ID, userID, id).
Updates(map[string]any{"project_id": "", "payload_json": canvas.PayloadJSON, "updated_at": canvas.UpdatedAt})
if result.Error != nil {
return result.Error
}
if result.RowsAffected != 1 {
return gorm.ErrRecordNotFound
}
}
var remainingCanvasCount int64
if err := tx.Model(&model.CanvasProject{}).Where("user_id = ? AND project_id = ?", userID, id).Count(&remainingCanvasCount).Error; err != nil {
return err
}
if remainingCanvasCount != 0 {
return fmt.Errorf("项目删除时仍有 %d 个画布关联未处理", remainingCanvasCount)
}
shotIDs := tx.Model(&model.Shot{}).Select("id").Where("project_id = ?", id)
if err := tx.Where("shot_id IN (?)", shotIDs).Delete(&model.ShotAssetReference{}).Error; err != nil {
return err
@@ -1023,6 +1074,12 @@ func (r *Repository) DeleteProject(userID string, id string) error {
if err := tx.Where("project_id = ?", id).Delete(&model.ProjectUnit{}).Error; err != nil {
return err
}
if err := tx.Model(&model.Task{}).Where("user_id = ? AND project_id = ?", userID, id).Update("project_id", "").Error; err != nil {
return err
}
if err := tx.Model(&model.Session{}).Where("user_id = ? AND project_id = ?", userID, id).Update("project_id", "").Error; err != nil {
return err
}
return tx.Delete(&model.Project{}, "id = ? AND user_id = ?", id, userID).Error
})
}