Semaphore/db/sql/task.go

235 lines
5.3 KiB
Go
Raw Normal View History

2021-03-12 18:41:41 +01:00
package sql
import (
"database/sql"
"github.com/Masterminds/squirrel"
"github.com/ansible-semaphore/semaphore/db"
"math/rand"
2021-03-12 18:41:41 +01:00
)
func (d *SqlDb) CreateTaskStage(stage db.TaskStage) (db.TaskStage, error) {
_, err := d.exec(
"insert into task__stage (task_id, type) VALUES (?, ?, ?, ?)",
stage.TaskID,
stage.Type,
stage.Start)
return stage, err
}
func (d *SqlDb) GetTaskStages(projectID int, taskID int) ([]db.TaskStage, error) {
return nil, nil
}
2024-06-30 09:48:36 +02:00
func (d *SqlDb) clearTasks(projectID int, templateID int, maxTasks int) {
tpl, err := d.GetTemplate(projectID, templateID)
if err != nil {
return
}
nTasks := tpl.Tasks
if rand.Intn(10) == 0 { // randomly recalculate number of tasks for the template
2024-06-30 09:48:36 +02:00
var n int64
n, err = d.sql.SelectInt("SELECT count(*) FROM task WHERE template_id=?", templateID)
if err != nil {
return
}
if n != int64(nTasks) {
2024-06-30 12:25:16 +02:00
_, err = d.exec("UPDATE `project__template` SET `tasks`=? WHERE project_id=? and id=?",
2024-06-30 09:48:36 +02:00
maxTasks, projectID, templateID)
if err != nil {
return
}
}
nTasks = int(n)
}
2024-06-30 15:48:59 +02:00
if nTasks < maxTasks+maxTasks/10 { // deadzone of 10% for clearing of old tasks
2024-06-30 09:48:36 +02:00
return
}
var oldestTask db.Task
err = d.selectOne(&oldestTask,
2024-06-30 12:25:16 +02:00
"SELECT created FROM task WHERE template_id=? ORDER BY created DESC LIMIT 1 OFFSET ?",
2024-06-30 09:48:36 +02:00
templateID, maxTasks-1)
if err != nil {
return
}
2024-06-30 12:25:16 +02:00
_, err = d.exec("DELETE FROM task WHERE template_id=? AND created>?", templateID, oldestTask.Created)
2024-06-30 09:48:36 +02:00
if err != nil {
return
}
2024-06-30 12:25:16 +02:00
_, _ = d.exec("UPDATE `project__template` SET `tasks`=? WHERE project_id=? and id=?",
2024-06-30 09:48:36 +02:00
maxTasks, projectID, templateID)
}
func (d *SqlDb) CreateTask(task db.Task, maxTasks int) (newTask db.Task, err error) {
err = d.sql.Insert(&task)
newTask = task
if err != nil {
return
}
2024-06-30 12:06:18 +02:00
_, err = d.exec("UPDATE `project__template` SET `tasks` = `tasks` + 1 WHERE project_id=? and id=?",
2024-06-30 09:48:36 +02:00
task.ProjectID, task.TemplateID)
if err != nil {
return
}
if maxTasks > 0 {
d.clearTasks(task.ProjectID, task.TemplateID, maxTasks)
}
return
2021-03-12 18:41:41 +01:00
}
func (d *SqlDb) UpdateTask(task db.Task) error {
2021-08-24 17:20:34 +02:00
_, err := d.exec(
"update task set status=?, start=?, `end`=? where id=?",
2021-03-12 18:41:41 +01:00
task.Status,
task.Start,
task.End,
task.ID)
return err
}
func (d *SqlDb) CreateTaskOutput(output db.TaskOutput) (db.TaskOutput, error) {
2021-08-24 17:20:34 +02:00
_, err := d.exec(
2021-03-12 18:41:41 +01:00
"insert into task__output (task_id, task, output, time) VALUES (?, '', ?, ?)",
output.TaskID,
output.Output,
output.Time)
return output, err
}
2024-06-29 18:23:41 +02:00
func (d *SqlDb) getTasks(projectID int, templateIDs []int, params db.RetrieveQueryParams, tasks *[]db.TaskWithTpl) (err error) {
2021-10-12 15:59:16 +02:00
fields := "task.*"
fields += ", tpl.playbook as tpl_playbook" +
", `user`.name as user_name" +
2022-02-03 08:05:13 +01:00
", tpl.name as tpl_alias" +
", tpl.type as tpl_type"
2021-10-12 15:59:16 +02:00
q := squirrel.Select(fields).
2021-03-12 18:41:41 +01:00
From("task").
Join("project__template as tpl on task.template_id=tpl.id").
LeftJoin("`user` on task.user_id=`user`.id").
2021-03-12 18:41:41 +01:00
OrderBy("task.created desc, id desc")
2024-06-30 12:06:18 +02:00
if params.Count > 0 {
q = q.Limit(uint64(params.Count))
}
type queryWithArgs struct {
sql string
args []interface{}
}
var queries []queryWithArgs
2024-06-29 18:23:41 +02:00
if len(templateIDs) == 0 {
2021-03-12 18:41:41 +01:00
q = q.Where("tpl.project_id=?", projectID)
2024-06-30 12:06:18 +02:00
query, args, _ := q.ToSql()
queries = append(queries, queryWithArgs{sql: query, args: args})
2021-03-12 18:41:41 +01:00
} else {
2024-06-30 12:06:18 +02:00
for _, templateID := range templateIDs {
query, args, _ := q.Where("tpl.project_id=? AND task.template_id=?", projectID, templateID).ToSql()
queries = append(queries, queryWithArgs{sql: query, args: args})
}
2021-03-12 18:41:41 +01:00
}
2024-06-30 12:06:18 +02:00
*tasks = []db.TaskWithTpl{}
2021-03-12 18:41:41 +01:00
2024-06-30 12:06:18 +02:00
for _, query := range queries {
var queryTasks []db.TaskWithTpl
_, err = d.selectAll(&queryTasks, query.sql, query.args...)
*tasks = append(*tasks, queryTasks...)
}
2021-03-12 18:41:41 +01:00
for i := range *tasks {
err = (*tasks)[i].Fill(d)
if err != nil {
return
}
}
2021-03-12 18:41:41 +01:00
return
}
func (d *SqlDb) GetTask(projectID int, taskID int) (task db.Task, err error) {
q := squirrel.Select("task.*").
From("task").
Join("project__template as tpl on task.template_id=tpl.id").
Where("tpl.project_id=? AND task.id=?", projectID, taskID)
query, args, err := q.ToSql()
if err != nil {
return
}
2021-08-24 17:20:34 +02:00
err = d.selectOne(&task, query, args...)
2021-03-12 18:41:41 +01:00
if err == sql.ErrNoRows {
err = db.ErrNotFound
return
}
if err != nil {
return
2021-03-12 18:41:41 +01:00
}
return
}
2024-06-29 18:23:41 +02:00
func (d *SqlDb) GetTemplateTasks(projectID int, templateIDs []int, params db.RetrieveQueryParams) (tasks []db.TaskWithTpl, err error) {
err = d.getTasks(projectID, templateIDs, params, &tasks)
2021-10-12 15:59:16 +02:00
return
2021-03-12 18:41:41 +01:00
}
2021-10-12 15:59:16 +02:00
func (d *SqlDb) GetProjectTasks(projectID int, params db.RetrieveQueryParams) (tasks []db.TaskWithTpl, err error) {
2024-06-30 12:06:18 +02:00
tasks = make([]db.TaskWithTpl, 0)
2021-10-12 15:59:16 +02:00
err = d.getTasks(projectID, nil, params, &tasks)
return
2021-03-12 18:41:41 +01:00
}
func (d *SqlDb) DeleteTaskWithOutputs(projectID int, taskID int) (err error) {
2021-03-12 21:20:18 +01:00
// check if task exists in the project
2021-03-12 18:41:41 +01:00
_, err = d.GetTask(projectID, taskID)
if err != nil {
return
}
2021-08-24 17:20:34 +02:00
_, err = d.exec("delete from task__output where task_id=?", taskID)
2021-03-12 18:41:41 +01:00
if err != nil {
return
}
2021-08-24 17:20:34 +02:00
_, err = d.exec("delete from task where id=?", taskID)
2021-03-12 18:41:41 +01:00
return
}
func (d *SqlDb) GetTaskOutputs(projectID int, taskID int) (output []db.TaskOutput, err error) {
2021-03-12 21:20:18 +01:00
// check if task exists in the project
_, err = d.GetTask(projectID, taskID)
if err != nil {
return
}
_, err = d.selectAll(&output,
2021-03-12 18:41:41 +01:00
"select task_id, task, time, output from task__output where task_id=? order by time asc",
taskID)
return
}