feat(T1.8): implement health checks for Kubernetes deployment

- Add internal/health package with health checker
- Implement three endpoints: /health, /health/live, /health/ready
- /health returns full JSON report with component status, latency, timestamp
- /health/live for K8s liveness probe (service running)
- /health/ready for K8s readiness probe (ready to accept traffic)
- Temporal connectivity check via GetWorkflow call with timeout
- Health check caching (30s interval) to prevent excessive checks
- Graceful shutdown: health server stops on SIGINT/SIGTERM
- Add --health flag to starter command to run health check
- Worker runs health server on port 8081 alongside task queue worker
- 10/10 unit tests passing
- All verification criteria met

Closes T1.8
This commit is contained in:
Test
2026-08-23 16:31:33 -07:00
parent e3a5e571bf
commit 90fcd6a9df
7 changed files with 612 additions and 10 deletions
+22 -6
View File
@@ -10,6 +10,7 @@ import (
"go.temporal.io/sdk/client"
"github.com/rockliang/poimen/workflows/internal/config"
"github.com/rockliang/poimen/workflows/internal/health"
"github.com/rockliang/poimen/workflows/statemachine"
)
@@ -22,15 +23,11 @@ func main() {
plannerModel = flag.String("planner-model", "ornith", "planner model ID")
judgeModel = flag.String("judge-model", "ornith", "judge model ID")
implementerModel = flag.String("implementer-model", "claude-sonnet-5", "implementer model ID")
healthCheck = flag.Bool("health", false, "check health and exit")
)
flag.Parse()
// Validate required flags
if *repoPath == "" || *remoteURL == "" {
log.Fatalf("--repo and --remote flags are required")
}
// Load configuration
// Load configuration first
cfg, err := config.LoadConfig()
if err != nil {
log.Fatalf("failed to load config: %v", err)
@@ -46,6 +43,25 @@ func main() {
}
defer c.Close()
// If health check requested, do it and exit
if *healthCheck {
healthChecker := health.NewChecker(c)
report := healthChecker.Check(context.Background())
jsonReport, _ := report.ToJSON()
fmt.Println(string(jsonReport))
if report.Status != health.StatusHealthy {
log.Fatalf("health check failed")
}
return
}
// Validate required flags for workflow start
if *repoPath == "" || *remoteURL == "" {
log.Fatalf("--repo and --remote flags are required")
}
// Build OrchestratorInput
input := statemachine.OrchestratorInput{
TargetRepoPath: *repoPath,