Compare commits
5 commits
b7f0ccc8a6
...
cd3c06d7d0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cd3c06d7d0 | ||
b03e85db0b | |||
77d7a8624c | |||
f4219fe0b2 | |||
07044f2dff |
9 changed files with 94 additions and 8 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE workers
|
||||||
|
DROP IF EXISTS queue_enable;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE workers
|
||||||
|
ADD queue_enable boolean NOT NULL DEFAULT false;
|
|
@ -16,8 +16,10 @@ type IndexData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type IndexWorker struct {
|
type IndexWorker struct {
|
||||||
|
ID string
|
||||||
Worker
|
Worker
|
||||||
Status *types.WorkerStatus
|
Status *types.WorkerStatus
|
||||||
|
QueueEnable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleIndex(w http.ResponseWriter, r *http.Request) {
|
func handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -39,11 +41,13 @@ func handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
slog.InfoContext(r.Context(), "Got Worker Status", "id", i, "status", status)
|
slog.InfoContext(r.Context(), "Got Worker Status", "id", i, "status", status)
|
||||||
data.Workers = append(data.Workers, IndexWorker{
|
data.Workers = append(data.Workers, IndexWorker{
|
||||||
|
ID: i,
|
||||||
Worker: *Workers[i],
|
Worker: *Workers[i],
|
||||||
Status: &status,
|
Status: &status,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
data.Workers = append(data.Workers, IndexWorker{
|
data.Workers = append(data.Workers, IndexWorker{
|
||||||
|
ID: i,
|
||||||
Worker: *Workers[i],
|
Worker: *Workers[i],
|
||||||
Status: nil,
|
Status: nil,
|
||||||
})
|
})
|
||||||
|
|
40
server/queue.go
Normal file
40
server/queue.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HandleSetQueueEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("Parseing Form: %v", err), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
enable := r.FormValue("enable")
|
||||||
|
if enable != "true" && enable != "false" {
|
||||||
|
http.Error(w, "Enable must be true or false", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
worker := r.FormValue("worker")
|
||||||
|
|
||||||
|
slog.Info("Got set Queue Enable", "enable", enable, "worker", worker)
|
||||||
|
|
||||||
|
if worker == "all" {
|
||||||
|
_, err = db.Exec(r.Context(), "UPDATE workers SET queue_enable = $1", enable)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("Setting Worker Queue Enable: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err = db.Exec(r.Context(), "UPDATE workers SET queue_enable = $1 where id = $2", enable, worker)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("Setting Worker Queue Enable: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusFound)
|
||||||
|
}
|
|
@ -101,6 +101,7 @@ func Start(_conf config.Config, tmplFS embed.FS, staticFS embed.FS, migrationsFS
|
||||||
mux.HandleFunc("/libraries/{id}", handleLibrary)
|
mux.HandleFunc("/libraries/{id}", handleLibrary)
|
||||||
mux.HandleFunc("/libraries", handleLibraries)
|
mux.HandleFunc("/libraries", handleLibraries)
|
||||||
mux.HandleFunc("/ffmpeg_commands", handleFfmpegCommands)
|
mux.HandleFunc("/ffmpeg_commands", handleFfmpegCommands)
|
||||||
|
mux.HandleFunc("/queue_enable", HandleSetQueueEnable)
|
||||||
|
|
||||||
mux.HandleFunc("/", handleIndex)
|
mux.HandleFunc("/", handleIndex)
|
||||||
|
|
||||||
|
|
|
@ -332,7 +332,18 @@ type QueuedTask struct {
|
||||||
FfmpegCommand types.FFmpegCommand `json:"ffmpeg_command" db:"ffmpeg_command"`
|
FfmpegCommand types.FFmpegCommand `json:"ffmpeg_command" db:"ffmpeg_command"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var assignRunning = false
|
||||||
|
|
||||||
func assignQueuedTasks(ctx context.Context) error {
|
func assignQueuedTasks(ctx context.Context) error {
|
||||||
|
if assignRunning {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
assignRunning = true
|
||||||
|
defer func() {
|
||||||
|
assignRunning = false
|
||||||
|
}()
|
||||||
|
|
||||||
rows, err := db.Query(ctx, "SELECT t.id as id, t.type as type, t.file_id as file_id, f.md5 as md5, t.data as data, fc.data as ffmpeg_command FROM tasks t INNER JOIN files f ON f.id = t.file_id INNER JOIN ffmpeg_commands fc ON fc.id = t.ffmpeg_command_id WHERE t.status = $1", constants.TASK_STATUS_QUEUED)
|
rows, err := db.Query(ctx, "SELECT t.id as id, t.type as type, t.file_id as file_id, f.md5 as md5, t.data as data, fc.data as ffmpeg_command FROM tasks t INNER JOIN files f ON f.id = t.file_id INNER JOIN ffmpeg_commands fc ON fc.id = t.ffmpeg_command_id WHERE t.status = $1", constants.TASK_STATUS_QUEUED)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Query Queued Tasks: %w", err)
|
return fmt.Errorf("Query Queued Tasks: %w", err)
|
||||||
|
@ -360,13 +371,23 @@ func assignQueuedTasks(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if Workers[i].Connected {
|
if Workers[i].Connected {
|
||||||
|
var queueEnable bool
|
||||||
|
err := db.QueryRow(ctx, "SELECT queue_enable FROM workers WHERE id = $1", i).Scan(&queueEnable)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Querying Worker Queue Enable: %w", err)
|
||||||
|
}
|
||||||
|
if !queueEnable {
|
||||||
|
slog.DebugContext(ctx, "Skipping Worker since Queueing is disabled", "worker_id", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
err := db.QueryRow(ctx, "SELECT COUNT(*) FROM tasks WHERE worker_id = $1 AND (status = $2 OR status = $3 OR status = $4 OR status = $5)", i, constants.TASK_STATUS_UNKNOWN, constants.TASK_STATUS_ASSIGNED, constants.TASK_STATUS_RUNNING, constants.TASK_STATUS_WAITING).Scan(&count)
|
err = db.QueryRow(ctx, "SELECT COUNT(*) FROM tasks WHERE worker_id = $1 AND (status = $2 OR status = $3 OR status = $4 OR status = $5)", i, constants.TASK_STATUS_UNKNOWN, constants.TASK_STATUS_ASSIGNED, constants.TASK_STATUS_RUNNING, constants.TASK_STATUS_WAITING).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error Querying Worker Task Count: %w", err)
|
return fmt.Errorf("Error Querying Worker Task Count: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Info("Assigning Queued Tasks Worker", "worker", i, "count", count)
|
slog.Debug("Assigning Queued Tasks Worker", "worker", i, "count", count)
|
||||||
|
|
||||||
// Allow for Multiple Tasks at once in the future
|
// Allow for Multiple Tasks at once in the future
|
||||||
if count < 1 {
|
if count < 1 {
|
||||||
|
@ -395,7 +416,7 @@ func assignQueuedTasks(ctx context.Context) error {
|
||||||
// Task was started previously but something went wrong and we are out of sync
|
// Task was started previously but something went wrong and we are out of sync
|
||||||
slog.WarnContext(ctx, "Task is apparently already Running on this Worker, thats bad", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
slog.WarnContext(ctx, "Task is apparently already Running on this Worker, thats bad", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
||||||
|
|
||||||
_, err = db.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_ASSIGNED, []string{fmt.Sprintf("%v MASTER: Task Start, Task Already Running!", time.Now())})
|
_, err = tx.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_ASSIGNED, []string{fmt.Sprintf("%v MASTER: Task Start, Task Already Running!", time.Now())})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Updating Task status during already running error: %w", err)
|
return fmt.Errorf("Updating Task status during already running error: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -403,14 +424,14 @@ func assignQueuedTasks(ctx context.Context) error {
|
||||||
// We really don't know whats going on, might be slow response, oom, disk full or a bug
|
// We really don't know whats going on, might be slow response, oom, disk full or a bug
|
||||||
slog.WarnContext(ctx, "Task start Timed Out", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
slog.WarnContext(ctx, "Task start Timed Out", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
||||||
|
|
||||||
_, err = db.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_UNKNOWN, []string{fmt.Sprintf("%v MASTER: Task Start RPC Call Timed Out!", time.Now())})
|
_, err = tx.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_UNKNOWN, []string{fmt.Sprintf("%v MASTER: Task Start RPC Call Timed Out!", time.Now())})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Updating Unknown Task Status due to Timeout while starting Task: %w", err)
|
return fmt.Errorf("Updating Unknown Task Status due to Timeout while starting Task: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
slog.ErrorContext(ctx, "Task start Error", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
slog.ErrorContext(ctx, "Task start Error", "task_id", taskStart.ID, "worker", Workers[i].Name)
|
||||||
|
|
||||||
_, err = db.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_UNKNOWN, []string{fmt.Sprintf("%v MASTER: Task Start Error: %v", time.Now(), err.Error())})
|
_, err = tx.Exec(ctx, "UPDATE tasks SET status = $2, log = log || $3 WHERE id = $1", taskStart.ID, constants.TASK_STATUS_UNKNOWN, []string{fmt.Sprintf("%v MASTER: Task Start Error: %v", time.Now(), err.Error())})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Updating Unknown Task Status due to Error while starting Task: %w", err)
|
return fmt.Errorf("Updating Unknown Task Status due to Error while starting Task: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ func readMessage(ctx context.Context, c *websocket.Conn) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.InfoContext(ctx, "Got Websocket Message", "type", t.String(), "data", data)
|
slog.DebugContext(ctx, "Got Websocket Message", "type", t.String(), "data", data)
|
||||||
rpcServer.HandleMessage(ctx, c, data)
|
rpcServer.HandleMessage(ctx, c, data)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,22 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
<h2>Set Queue Enable</h2>
|
||||||
|
<form method="POST" action= "/queue_enable">
|
||||||
|
<label for="worker">Worker:</label>
|
||||||
|
<select id="worker" name="worker">
|
||||||
|
<option value="all">All</option>
|
||||||
|
{{range $w := .Workers}}
|
||||||
|
<option value="{{$w.ID}}">{{$w.Name}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
<label for="enable">Enable</label>
|
||||||
|
<select id="enable" name="enable">
|
||||||
|
<option value="true">True</option>
|
||||||
|
<option value="false">False</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
<h2>Workers</h2>
|
<h2>Workers</h2>
|
||||||
<div class="workers">
|
<div class="workers">
|
||||||
{{range $w := .Workers}}
|
{{range $w := .Workers}}
|
||||||
|
|
|
@ -116,7 +116,7 @@ func readMessage(ctx context.Context, c *websocket.Conn) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.InfoContext(ctx, "Got Websocket Message", "type", t.String(), "data", data)
|
slog.DebugContext(ctx, "Got Websocket Message", "type", t.String(), "data", data)
|
||||||
rpcServer.HandleMessage(ctx, c, data)
|
rpcServer.HandleMessage(ctx, c, data)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue