diff --git a/internal/api/job.go b/internal/api/job.go index 65584ca..7701374 100644 --- a/internal/api/job.go +++ b/internal/api/job.go @@ -882,6 +882,7 @@ func (api *RestAPI) deleteJobByRequest(rw http.ResponseWriter, r *http.Request) // @failure 500 {object} api.ErrorResponse "Internal Server Error" // @security ApiKeyAuth // @router /api/jobs/delete_job_before/{ts} [delete] +// @param omit-tagged query bool false "Omit jobs with tags from deletion" func (api *RestAPI) deleteJobBefore(rw http.ResponseWriter, r *http.Request) { var cnt int // Fetch job (that will be stopped) from db @@ -894,7 +895,17 @@ func (api *RestAPI) deleteJobBefore(rw http.ResponseWriter, r *http.Request) { return } - cnt, err = api.JobRepository.DeleteJobsBefore(ts) + // Check for omit-tagged query parameter + omitTagged := false + if omitTaggedStr := r.URL.Query().Get("omit-tagged"); omitTaggedStr != "" { + omitTagged, e = strconv.ParseBool(omitTaggedStr) + if e != nil { + handleError(fmt.Errorf("boolean expected for omit-tagged parameter: %w", e), http.StatusBadRequest, rw) + return + } + } + + cnt, err = api.JobRepository.DeleteJobsBefore(ts, omitTagged) } else { handleError(errors.New("the parameter 'ts' is required"), http.StatusBadRequest, rw) return diff --git a/internal/repository/job.go b/internal/repository/job.go index 34c37e6..2f003e3 100644 --- a/internal/repository/job.go +++ b/internal/repository/job.go @@ -321,9 +321,14 @@ func (r *JobRepository) FetchEnergyFootprint(job *schema.Job) (map[string]float6 return job.EnergyFootprint, nil } -func (r *JobRepository) DeleteJobsBefore(startTime int64) (int, error) { +func (r *JobRepository) DeleteJobsBefore(startTime int64, omitTagged bool) (int, error) { var cnt int q := sq.Select("count(*)").From("job").Where("job.start_time < ?", startTime) + + if omitTagged { + q = q.Where("NOT EXISTS (SELECT 1 FROM jobtag WHERE jobtag.job_id = job.id)") + } + if err := q.RunWith(r.DB).QueryRow().Scan(&cnt); err != nil { cclog.Errorf("Error counting jobs before %d: %v", startTime, err) return 0, err @@ -332,7 +337,13 @@ func (r *JobRepository) DeleteJobsBefore(startTime int64) (int, error) { // Invalidate cache for jobs being deleted (get job IDs first) if cnt > 0 { var jobIds []int64 - rows, err := sq.Select("id").From("job").Where("job.start_time < ?", startTime).RunWith(r.DB).Query() + selectQuery := sq.Select("id").From("job").Where("job.start_time < ?", startTime) + + if omitTagged { + selectQuery = selectQuery.Where("NOT EXISTS (SELECT 1 FROM jobtag WHERE jobtag.job_id = job.id)") + } + + rows, err := selectQuery.RunWith(r.DB).Query() if err == nil { defer rows.Close() for rows.Next() { @@ -350,6 +361,10 @@ func (r *JobRepository) DeleteJobsBefore(startTime int64) (int, error) { } qd := sq.Delete("job").Where("job.start_time < ?", startTime) + + if omitTagged { + qd = qd.Where("NOT EXISTS (SELECT 1 FROM jobtag WHERE jobtag.job_id = job.id)") + } _, err := qd.RunWith(r.DB).Exec() if err != nil { diff --git a/internal/taskmanager/retentionService.go b/internal/taskmanager/retentionService.go index e452ffd..0a61bc4 100644 --- a/internal/taskmanager/retentionService.go +++ b/internal/taskmanager/retentionService.go @@ -27,7 +27,7 @@ func RegisterRetentionDeleteService(age int, includeDB bool, omitTagged bool) { archive.GetHandle().CleanUp(jobs) if includeDB { - cnt, err := jobRepo.DeleteJobsBefore(startTime) + cnt, err := jobRepo.DeleteJobsBefore(startTime, omitTagged) if err != nil { cclog.Errorf("Error while deleting retention jobs from db: %s", err.Error()) } else { @@ -54,7 +54,7 @@ func RegisterRetentionMoveService(age int, includeDB bool, location string, omit archive.GetHandle().Move(jobs, location) if includeDB { - cnt, err := jobRepo.DeleteJobsBefore(startTime) + cnt, err := jobRepo.DeleteJobsBefore(startTime, omitTagged) if err != nil { cclog.Errorf("Error while deleting retention jobs from db: %v", err) } else {