heroagent/_pkg2_dont_use/heroagent/pages/jobs.go
2025-05-23 16:10:49 +04:00

188 lines
5.6 KiB
Go

package pages
import (
"fmt"
"log"
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
"github.com/gofiber/fiber/v2"
)
// JobDisplayInfo represents information about a job for display purposes
type JobDisplayInfo struct {
JobID string `json:"jobid"`
CircleID string `json:"circleid"`
Topic string `json:"topic"`
Status string `json:"status"`
SessionKey string `json:"sessionkey"`
Params string `json:"params"`
ParamsType string `json:"paramstype"`
Result string `json:"result"`
Error string `json:"error"`
TimeScheduled int64 `json:"time_scheduled"`
TimeStart int64 `json:"time_start"`
TimeEnd int64 `json:"time_end"`
Timeout int64 `json:"timeout"`
}
// JobHandler handles job-related page routes
type JobHandler struct {
client *herojobs.RedisClient
logger *log.Logger
}
// NewJobHandler creates a new job handler with the provided socket path
func NewJobHandler(redisAddr string, logger *log.Logger) (*JobHandler, error) {
// Assuming SSL is false as per README example herojobs.NewRedisClient("localhost:6379", false)
// This might need to be configurable later.
client, err := herojobs.NewRedisClient(redisAddr, false)
if err != nil {
return nil, fmt.Errorf("failed to create HeroJobs Redis client: %w", err)
}
return &JobHandler{
client: client,
logger: logger,
}, nil
}
// RegisterRoutes registers job page routes
func (h *JobHandler) RegisterRoutes(app *fiber.App) {
// Register routes for /jobs
jobs := app.Group("/jobs")
jobs.Get("/", h.getJobsPage)
jobs.Get("/list", h.getJobsList)
// Register the same routes under /admin/jobs for consistency
adminJobs := app.Group("/admin/jobs")
adminJobs.Get("/", h.getJobsPage)
adminJobs.Get("/list", h.getJobsList)
}
// getJobsPage renders the jobs page
func (h *JobHandler) getJobsPage(c *fiber.Ctx) error {
// Assuming h.client (RedisClient) is valid if NewJobHandler succeeded.
// The client is connected on creation. A Ping method could be used here for a health check if available.
// The previous connect/close logic per-request is removed.
var warning string // This will be empty unless a new check (e.g., Ping) sets it.
return c.Render("admin/jobs", fiber.Map{
"title": "Jobs",
"warning": warning, // warning will be empty for now
"error": "",
})
}
// getJobsList returns the jobs list fragment for AJAX updates
func (h *JobHandler) getJobsList(c *fiber.Ctx) error {
// Get parameters from query
circleID := c.Query("circleid", "")
topic := c.Query("topic", "")
// Get jobs
jobs, err := h.getJobsData(circleID, topic)
if err != nil {
h.logger.Printf("Error getting jobs: %v", err)
// Return the error in the template
return c.Render("admin/jobs_list_fragment", fiber.Map{
"error": fmt.Sprintf("Failed to get jobs: %v", err),
"jobs": []JobDisplayInfo{},
})
}
// Render only the jobs fragment
return c.Render("admin/jobs_list_fragment", fiber.Map{
"jobs": jobs,
})
}
// getJobsData gets job data from the HeroJobs server
func (h *JobHandler) getJobsData(circleID, topic string) ([]JobDisplayInfo, error) {
// Assuming h.client (RedisClient) is already connected (established by NewJobHandler).
// It should not be closed here as it's a long-lived client.
// Connect() and Close() calls per-request are removed.
// If circleID and topic are not provided, try to list all jobs
if circleID == "" && topic == "" {
// Try to get some default jobs
defaultCircles := []string{"default", "system"}
defaultTopics := []string{"default", "system"}
var allJobs []JobDisplayInfo
// Try each combination
for _, circle := range defaultCircles {
for _, t := range defaultTopics {
jobIDs, err := h.client.ListJobs(circle, t)
if err != nil {
h.logger.Printf("Could not list jobs for circle=%s, topic=%s: %v", circle, t, err)
continue
}
for _, jobID := range jobIDs {
job, err := h.client.GetJob(jobID)
if err != nil {
h.logger.Printf("Error getting job %s: %v", jobID, err)
continue
}
allJobs = append(allJobs, JobDisplayInfo{
JobID: fmt.Sprintf("%d", job.JobID),
CircleID: job.CircleID,
Topic: job.Topic,
Status: string(job.Status),
SessionKey: job.SessionKey,
Params: job.Params,
ParamsType: string(job.ParamsType),
Result: job.Result,
Error: job.Error,
TimeScheduled: job.TimeScheduled,
TimeStart: job.TimeStart,
TimeEnd: job.TimeEnd,
Timeout: job.Timeout,
})
}
}
}
return allJobs, nil
} else if circleID == "" || topic == "" {
// If only one of the parameters is provided, we can't list jobs
return []JobDisplayInfo{}, nil
}
// List jobs
jobIDs, err := h.client.ListJobs(circleID, topic)
if err != nil {
return nil, fmt.Errorf("failed to list jobs: %w", err)
}
// Get details for each job
jobsList := make([]JobDisplayInfo, 0, len(jobIDs))
for _, jobID := range jobIDs {
job, err := h.client.GetJob(jobID)
if err != nil {
h.logger.Printf("Error getting job %s: %v", jobID, err)
continue
}
jobInfo := JobDisplayInfo{
JobID: fmt.Sprintf("%d", job.JobID),
CircleID: job.CircleID,
Topic: job.Topic,
Status: string(job.Status),
SessionKey: job.SessionKey,
Params: job.Params,
ParamsType: string(job.ParamsType),
Result: job.Result,
Error: job.Error,
TimeScheduled: job.TimeScheduled,
TimeStart: job.TimeStart,
TimeEnd: job.TimeEnd,
Timeout: job.Timeout,
}
jobsList = append(jobsList, jobInfo)
}
return jobsList, nil
}