feat(model): add Task model, DTOs, and status constants for task submission system

This commit is contained in:
dailz
2026-04-15 21:30:44 +08:00
parent 79870333cb
commit d46a784efb
2 changed files with 197 additions and 0 deletions

104
internal/model/task_test.go Normal file
View File

@@ -0,0 +1,104 @@
package model
import (
"encoding/json"
"testing"
"time"
)
func TestTask_TableName(t *testing.T) {
task := Task{}
if got := task.TableName(); got != "hpc_tasks" {
t.Errorf("Task.TableName() = %q, want %q", got, "hpc_tasks")
}
}
func TestTask_JSONRoundTrip(t *testing.T) {
now := time.Now().UTC().Truncate(time.Second)
jobID := int32(42)
task := Task{
ID: 1,
TaskName: "test task",
AppID: 10,
AppName: "GROMACS",
Status: TaskStatusRunning,
CurrentStep: TaskStepSubmitting,
RetryCount: 1,
Values: json.RawMessage(`{"np":"4"}`),
InputFileIDs: json.RawMessage(`[1,2,3]`),
Script: "#!/bin/bash",
SlurmJobID: &jobID,
WorkDir: "/data/work",
Partition: "gpu",
ErrorMessage: "",
UserID: "user1",
SubmittedAt: now,
StartedAt: &now,
FinishedAt: nil,
CreatedAt: now,
UpdatedAt: now,
}
data, err := json.Marshal(task)
if err != nil {
t.Fatalf("marshal task: %v", err)
}
var got Task
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal task: %v", err)
}
if got.ID != task.ID {
t.Errorf("ID = %d, want %d", got.ID, task.ID)
}
if got.TaskName != task.TaskName {
t.Errorf("TaskName = %q, want %q", got.TaskName, task.TaskName)
}
if got.Status != task.Status {
t.Errorf("Status = %q, want %q", got.Status, task.Status)
}
if got.CurrentStep != task.CurrentStep {
t.Errorf("CurrentStep = %q, want %q", got.CurrentStep, task.CurrentStep)
}
if got.RetryCount != task.RetryCount {
t.Errorf("RetryCount = %d, want %d", got.RetryCount, task.RetryCount)
}
if got.SlurmJobID == nil || *got.SlurmJobID != jobID {
t.Errorf("SlurmJobID = %v, want %d", got.SlurmJobID, jobID)
}
if got.UserID != task.UserID {
t.Errorf("UserID = %q, want %q", got.UserID, task.UserID)
}
if string(got.Values) != string(task.Values) {
t.Errorf("Values = %s, want %s", got.Values, task.Values)
}
if string(got.InputFileIDs) != string(task.InputFileIDs) {
t.Errorf("InputFileIDs = %s, want %s", got.InputFileIDs, task.InputFileIDs)
}
if got.FinishedAt != nil {
t.Errorf("FinishedAt = %v, want nil", got.FinishedAt)
}
}
func TestCreateTaskRequest_JSONBinding(t *testing.T) {
payload := `{"app_id":5,"task_name":"my task","values":{"np":"8"},"file_ids":[10,20]}`
var req CreateTaskRequest
if err := json.Unmarshal([]byte(payload), &req); err != nil {
t.Fatalf("unmarshal CreateTaskRequest: %v", err)
}
if req.AppID != 5 {
t.Errorf("AppID = %d, want 5", req.AppID)
}
if req.TaskName != "my task" {
t.Errorf("TaskName = %q, want %q", req.TaskName, "my task")
}
if v, ok := req.Values["np"]; !ok || v != "8" {
t.Errorf("Values[\"np\"] = %q, want %q", v, "8")
}
if len(req.InputFileIDs) != 2 || req.InputFileIDs[0] != 10 || req.InputFileIDs[1] != 20 {
t.Errorf("InputFileIDs = %v, want [10 20]", req.InputFileIDs)
}
}