refactor: implement worker pool pattern, add persistent task queue, and decouple target loading logic
This commit is contained in:
+58
-19
@@ -1,7 +1,6 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -9,20 +8,20 @@ import (
|
||||
|
||||
"github.com/hireme/hireme/internal/config"
|
||||
"github.com/hireme/hireme/internal/db"
|
||||
"github.com/hireme/hireme/internal/service"
|
||||
"github.com/hireme/hireme/internal/worker"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
cfg *config.Config
|
||||
db *db.DB
|
||||
pipeline *service.PipelineService
|
||||
cfg *config.Config
|
||||
db *db.DB
|
||||
pool *worker.WorkerPool
|
||||
}
|
||||
|
||||
func NewServer(cfg *config.Config, database *db.DB, pipeline *service.PipelineService) *Server {
|
||||
func NewServer(cfg *config.Config, database *db.DB, pool *worker.WorkerPool) *Server {
|
||||
return &Server{
|
||||
cfg: cfg,
|
||||
db: database,
|
||||
pipeline: pipeline,
|
||||
cfg: cfg,
|
||||
db: database,
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +35,9 @@ func (s *Server) RegisterRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /jobs/{id}/analyze", s.handleAnalyzeJob)
|
||||
mux.HandleFunc("POST /applications", s.handleCreateApplication)
|
||||
mux.HandleFunc("PATCH /applications/{id}/status", s.handleUpdateAppStatus)
|
||||
mux.HandleFunc("POST /pipeline/run", s.handleRunPipeline)
|
||||
mux.HandleFunc("POST /api/tasks/discover", s.handleDiscoverTasks)
|
||||
mux.HandleFunc("POST /api/tasks/clean", s.handleCleanTasks)
|
||||
mux.HandleFunc("POST /api/tasks/toggle", s.handleToggleTasks)
|
||||
}
|
||||
|
||||
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -175,14 +176,16 @@ func (s *Server) handleAnalyzeJob(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
job, err := s.pipeline.AnalyzeJobByID(r.Context(), id)
|
||||
// Enqueue analyze task instead of synchronous processing
|
||||
payload := worker.AnalyzePayload{RawJobID: int64(id)}
|
||||
err = s.db.EnqueueTask("ANALYZE", payload)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, "Failed to enqueue analysis task: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
_ = RenderJobDetail(w, job)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
_, _ = w.Write([]byte(`<span class="text-xs px-2 py-1 bg-yellow-100 text-yellow-800 rounded">Analysis Queued</span>`))
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateApplication(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -269,12 +272,48 @@ func (s *Server) handleUpdateAppStatus(w http.ResponseWriter, r *http.Request) {
|
||||
_ = RenderKanbanBoard(w, updatedApps)
|
||||
}
|
||||
|
||||
func (s *Server) handleRunPipeline(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.Background()
|
||||
_, _, err := s.pipeline.RunPipeline(ctx)
|
||||
func (s *Server) handleDiscoverTasks(w http.ResponseWriter, r *http.Request) {
|
||||
targets, err := s.db.GetAllTargets()
|
||||
if err != nil {
|
||||
log.Printf("[Server] Pipeline run error: %v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
s.handleGetJobs(w, r)
|
||||
count := 0
|
||||
for _, target := range targets {
|
||||
if !target.IsActive {
|
||||
continue
|
||||
}
|
||||
payload := worker.DiscoverPayload{
|
||||
TargetID: target.ID,
|
||||
TargetURL: target.TargetURL,
|
||||
Platform: target.Platform,
|
||||
}
|
||||
if err := s.db.EnqueueTask("DISCOVER", payload); err == nil {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"status": "success", "message": "Queued ` + strconv.Itoa(count) + ` discovery tasks"}`))
|
||||
}
|
||||
|
||||
func (s *Server) handleCleanTasks(w http.ResponseWriter, r *http.Request) {
|
||||
err := s.db.ClearTaskQueue()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"status": "success"}`))
|
||||
}
|
||||
|
||||
func (s *Server) handleToggleTasks(w http.ResponseWriter, r *http.Request) {
|
||||
isRunning := s.pool.Toggle()
|
||||
status := "paused"
|
||||
if isRunning {
|
||||
status = "running"
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"status": "` + status + `"}`))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user