From d83517f67ba638abed1d76541068413e60142194 Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch Date: Thu, 26 Dec 2024 18:41:29 +0100 Subject: Refresh task view dynamically with Javascript This is more efficient, responsive, and user friendly. --- acid.go | 231 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 178 insertions(+), 53 deletions(-) (limited to 'acid.go') diff --git a/acid.go b/acid.go index cdf9007..62687f4 100644 --- a/acid.go +++ b/acid.go @@ -263,53 +263,182 @@ var templateTask = template.Must(template.New("tasks").Parse(` Task {{.ID}} -{{if .IsRunning}} - -{{end}}

Tasks » {{.ID}}

-{{if .Created}} + +{{if .Created -}}
Created
-
{{.CreatedAgo}} ago
-{{end}} -{{if .Changed}} +
{{.CreatedAgo}} ago
+{{end -}} +{{if .Changed -}}
Changed
-
{{.ChangedAgo}} ago
-{{end}} +
{{.ChangedAgo}} ago
+{{end -}}
Project
-
{{.FullName}}
+
{{.FullName}}
Commit
-
{{.Hash}}
+
{{.Hash}}
Runner
-
{{.RunnerName}}
+
{{.RunnerName}}
State
-
{{.State}}{{if .Detail}} ({{.Detail}}){{end}}
+
{{.State}}{{if .Detail}} ({{.Detail}}){{end}}
Notified
-
{{.Notified}}
-{{if .Duration}} +
{{.Notified}}
Duration
-
{{.Duration}}
-{{end}} +
{{if .Duration}}{{.Duration}}{{else}}—{{end}}
-{{if .RunLog}} -

Runner log

-
{{printf "%s" .RunLog}}
-{{end}} -{{if .TaskLog}} -

Task log

-
{{printf "%s" .TaskLog}}
-{{end}} -{{if .DeployLog}} -

Deploy log

-
{{printf "%s" .DeployLog}}
-{{end}} - + +

Runner log

+
{{printf "%s" .RunLog}}
+

Task log

+
{{printf "%s" .TaskLog}}
+

Deploy log

+
{{printf "%s" .DeployLog}}
+ +{{if .IsRunning -}} + +{{end -}} + `)) +// handlerTask serves as the data for JSON encoding and the task HTML template. +// It needs to explicitly include many convenience method results. +type handlerTask struct { + Task + IsRunning bool + + Created *string // Task.Created?.String() + Changed *string // Task.Changed?.String() + CreatedAgo string // Task.CreatedAgo() + ChangedAgo string // Task.ChangedAgo() + Duration *string // Task.Duration?.String() + State string // Task.State.String() + RunLog string + RunLogTop int + TaskLog string + TaskLogTop int + DeployLog string + DeployLogTop int +} + +func toNilableString[T fmt.Stringer](stringer *T) *string { + if stringer == nil { + return nil + } + s := (*stringer).String() + return &s +} + +func newHandlerTask(task Task) handlerTask { + return handlerTask{ + Task: task, + RunLog: string(task.RunLog), + TaskLog: string(task.TaskLog), + DeployLog: string(task.DeployLog), + + Created: toNilableString(task.Created()), + Changed: toNilableString(task.Changed()), + CreatedAgo: task.CreatedAgo(), + ChangedAgo: task.ChangedAgo(), + Duration: toNilableString(task.Duration()), + State: task.State.String(), + } +} + +func (ht *handlerTask) updateFromRunning( + rt *RunningTask, lastRun, lastTask, lastDeploy int) { + ht.IsRunning = true + ht.Task.DurationSeconds = rt.elapsed() + ht.Duration = toNilableString(ht.Task.Duration()) + + rt.RunLog.Lock() + defer rt.RunLog.Unlock() + rt.TaskLog.Lock() + defer rt.TaskLog.Unlock() + rt.DeployLog.Lock() + defer rt.DeployLog.Unlock() + + ht.RunLog, ht.RunLogTop = rt.RunLog.SerializeUpdates(lastRun) + ht.TaskLog, ht.TaskLogTop = rt.TaskLog.SerializeUpdates(lastTask) + ht.DeployLog, ht.DeployLogTop = rt.DeployLog.SerializeUpdates(lastDeploy) +} + func handleTask(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.PathValue("id")) if err != nil { @@ -330,36 +459,32 @@ func handleTask(w http.ResponseWriter, r *http.Request) { return } - task := struct { - Task - IsRunning bool - }{Task: tasks[0]} + // These are intended for running tasks, + // so don't reprocess DB logs, which would only help the last update. + q := r.URL.Query() + lastRun, _ := strconv.Atoi(q.Get("run")) + lastTask, _ := strconv.Atoi(q.Get("task")) + lastDeploy, _ := strconv.Atoi(q.Get("deploy")) + + task := newHandlerTask(tasks[0]) func() { gRunningMutex.Lock() defer gRunningMutex.Unlock() - rt, ok := gRunning[task.ID] - task.IsRunning = ok - if !ok { - return + if rt, ok := gRunning[task.ID]; ok { + task.updateFromRunning( + rt, int(lastRun), int(lastTask), int(lastDeploy)) } - - task.DurationSeconds = rt.elapsed() - - rt.RunLog.Lock() - defer rt.RunLog.Unlock() - rt.TaskLog.Lock() - defer rt.TaskLog.Unlock() - rt.DeployLog.Lock() - defer rt.DeployLog.Unlock() - - task.RunLog = rt.RunLog.Serialize(0) - task.TaskLog = rt.TaskLog.Serialize(0) - task.DeployLog = rt.DeployLog.Serialize(0) }() - if err := templateTask.Execute(w, &task); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + if q.Has("json") { + w.Header().Set("Content-Type", "application/json") + err = json.NewEncoder(w).Encode(&task) + } else { + err = templateTask.Execute(w, &task) + } + if err != nil { + log.Println(err) } } -- cgit v1.2.3-70-g09d2