package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "go.temporal.io/sdk/client" "go.temporal.io/sdk/worker" "github.com/rockliang/poimen/workflows/action" "github.com/rockliang/poimen/workflows/internal/config" "github.com/rockliang/poimen/workflows/internal/health" "github.com/rockliang/poimen/workflows/statemachine" ) func main() { // Load configuration cfg, err := config.LoadConfig() if err != nil { log.Fatalf("failed to load config: %v", err) } // Connect to Temporal c, err := client.Dial(client.Options{ HostPort: cfg.Temporal.HostPort, Namespace: cfg.Temporal.Namespace, }) if err != nil { log.Fatalf("failed to connect to temporal: %v", err) } defer c.Close() // Create worker w := worker.New(c, "poimen-taskqueue", worker.Options{}) if w == nil { log.Fatalf("failed to create worker") } // Register all workflows w.RegisterWorkflow(statemachine.OrchestratorWorkflow) w.RegisterWorkflow(statemachine.TaskUnitWorkflow) w.RegisterWorkflow(statemachine.TestWorkflow) // Register all activities w.RegisterActivity(action.CloneRepoActivity) w.RegisterActivity(action.GitWorktreeAddActivity) w.RegisterActivity(action.GitCommitActivity) w.RegisterActivity(action.GitPushActivity) w.RegisterActivity(action.GitSquashMergeActivity) w.RegisterActivity(action.GitDiffActivity) w.RegisterActivity(action.PrepareSkillsActivity) w.RegisterActivity(action.PlanningActivity) w.RegisterActivity(action.ImplementerActivity) w.RegisterActivity(action.JudgeActivity) // Integration and lessons activities - register when fully tested // w.RegisterActivity(action.RunIntegrationTestActivity) // w.RegisterActivity(action.UpdateLessonsActivity) // w.RegisterActivity(action.ReadLessonsActivity) // Initialize health checker healthChecker := health.NewChecker(c) healthHandler := health.NewHandler(healthChecker) // Set up HTTP server for health checks mux := http.NewServeMux() healthHandler.RegisterRoutes(mux) healthServer := &http.Server{ Addr: ":8081", Handler: mux, } // Start health check server in a goroutine go func() { log.Printf("Health check server listening on %s", healthServer.Addr) if err := healthServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Printf("health check server error: %v", err) } }() // Set up signal handling for graceful shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // Run worker in a goroutine workerErrChan := make(chan error, 1) go func() { fmt.Println("Starting worker on queue 'poimen-taskqueue'...") if err := w.Run(worker.InterruptCh()); err != nil { workerErrChan <- err } }() // Wait for either worker error or signal select { case err := <-workerErrChan: log.Fatalf("worker failed: %v", err) case sig := <-sigChan: log.Printf("received signal: %v, shutting down gracefully", sig) w.Stop() // Shutdown health check server ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := healthServer.Shutdown(ctx); err != nil { log.Printf("health check server shutdown error: %v", err) } } }