From 8177703d6f8b15b6992feb159403a934a80583c5 Mon Sep 17 00:00:00 2001 From: Nathan Cochran Date: Fri, 10 Oct 2025 11:41:23 -0400 Subject: [PATCH 1/2] Fix service_create status/connection string bug when waiting --- internal/tiger/cmd/service.go | 8 ++++---- internal/tiger/mcp/service_tools.go | 5 ++--- internal/tiger/mcp/utils.go | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/internal/tiger/cmd/service.go b/internal/tiger/cmd/service.go index 1a45f76c..b8e2db50 100644 --- a/internal/tiger/cmd/service.go +++ b/internal/tiger/cmd/service.go @@ -442,7 +442,7 @@ Note: You can specify both CPU and memory together, or specify only one (the oth } else { // Wait for service to be ready fmt.Fprintf(statusOutput, "⏳ Waiting for service to be ready (wait timeout: %v)...\n", createWaitTimeout) - service.Status, result = waitForServiceReady(client, projectID, serviceID, createWaitTimeout, statusOutput) + service.Status, result = waitForServiceReady(client, projectID, serviceID, createWaitTimeout, service.Status, statusOutput) if result != nil { fmt.Fprintf(statusOutput, "❌ %v\n", result) } else { @@ -841,14 +841,14 @@ func formatTimePtr(t *time.Time) string { } // waitForServiceReady polls the service status until it's ready or timeout occurs -func waitForServiceReady(client *api.ClientWithResponses, projectID, serviceID string, waitTimeout time.Duration, output io.Writer) (*api.DeployStatus, error) { +func waitForServiceReady(client *api.ClientWithResponses, projectID, serviceID string, waitTimeout time.Duration, initialStatus *api.DeployStatus, output io.Writer) (*api.DeployStatus, error) { ctx, cancel := context.WithTimeout(context.Background(), waitTimeout) defer cancel() ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() - var lastStatus *api.DeployStatus + lastStatus := initialStatus for { select { case <-ctx.Done(): @@ -1312,7 +1312,7 @@ Examples: } else { // Wait for service to be ready fmt.Fprintf(statusOutput, "⏳ Waiting for fork to complete (timeout: %v)...\n", forkWaitTimeout) - forkedService.Status, result = waitForServiceReady(client, projectID, forkedServiceID, forkWaitTimeout, statusOutput) + forkedService.Status, result = waitForServiceReady(client, projectID, forkedServiceID, forkWaitTimeout, forkedService.Status, statusOutput) if result != nil { fmt.Fprintf(statusOutput, "❌ %v\n", result) } else { diff --git a/internal/tiger/mcp/service_tools.go b/internal/tiger/mcp/service_tools.go index 68e870f3..326729e3 100644 --- a/internal/tiger/mcp/service_tools.go +++ b/internal/tiger/mcp/service_tools.go @@ -507,7 +507,6 @@ func (s *Server) handleServiceCreate(ctx context.Context, req *mcp.CallToolReque service := *resp.JSON202 serviceID := util.Deref(service.ServiceId) - serviceStatus := util.DerefStr(service.Status) output := ServiceCreateOutput{ Service: s.convertToServiceDetail(service), @@ -558,10 +557,10 @@ func (s *Server) handleServiceCreate(ctx context.Context, req *mcp.CallToolReque if input.Wait { timeout := time.Duration(*input.TimeoutMinutes) * time.Minute - output.Service, err = s.waitForServiceReady(apiClient, cfg.ProjectID, serviceID, timeout, serviceStatus) - if err != nil { + if status, err := s.waitForServiceReady(apiClient, cfg.ProjectID, serviceID, timeout, service.Status); err != nil { output.Message = fmt.Sprintf("Error: %s", err.Error()) } else { + output.Service.Status = util.DerefStr(status) output.Message = "Service created successfully and is ready!" } } diff --git a/internal/tiger/mcp/utils.go b/internal/tiger/mcp/utils.go index c0aef95d..a247529f 100644 --- a/internal/tiger/mcp/utils.go +++ b/internal/tiger/mcp/utils.go @@ -128,7 +128,7 @@ func (s *Server) convertToServiceDetail(service api.Service) ServiceDetail { // waitForServiceReady polls the service status until it's ready or timeout occurs // Returns the final ServiceDetail with current state and any error that occurred -func (s *Server) waitForServiceReady(apiClient *api.ClientWithResponses, projectID, serviceID string, timeout time.Duration, initialStatus string) (ServiceDetail, error) { +func (s *Server) waitForServiceReady(apiClient *api.ClientWithResponses, projectID, serviceID string, timeout time.Duration, initialStatus *api.DeployStatus) (*api.DeployStatus, error) { logging.Debug("MCP: Waiting for service to be ready", zap.String("service_id", serviceID), zap.Duration("timeout", timeout), @@ -140,12 +140,12 @@ func (s *Server) waitForServiceReady(apiClient *api.ClientWithResponses, project ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() - var lastService ServiceDetail + lastStatus := initialStatus for { select { case <-ctx.Done(): logging.Warn("MCP: Timed out while waiting for service to be ready", zap.Error(ctx.Err())) - return lastService, fmt.Errorf("timeout reached after %v - service may still be provisioning", timeout) + return lastStatus, fmt.Errorf("timeout reached after %v - service may still be provisioning", timeout) case <-ticker.C: resp, err := apiClient.GetProjectsProjectIdServicesServiceIdWithResponse(ctx, projectID, serviceID) if err != nil { @@ -158,18 +158,20 @@ func (s *Server) waitForServiceReady(apiClient *api.ClientWithResponses, project continue } - lastService = s.convertToServiceDetail(*resp.JSON200) + service := *resp.JSON200 + lastStatus = service.Status + status := util.DerefStr(service.Status) - switch lastService.Status { + switch status { case "READY": logging.Debug("MCP: Service is ready", zap.String("service_id", serviceID)) - return lastService, nil + return service.Status, nil case "FAILED", "ERROR": - return lastService, fmt.Errorf("service creation failed with status: %s", lastService.Status) + return service.Status, fmt.Errorf("service creation failed with status: %s", status) default: logging.Debug("MCP: Service status", zap.String("service_id", serviceID), - zap.String("status", lastService.Status), + zap.String("status", status), ) } } From 618bea1c8df37078ebd8b44825240197c91a7afd Mon Sep 17 00:00:00 2001 From: Nathan Cochran Date: Fri, 10 Oct 2025 11:52:25 -0400 Subject: [PATCH 2/2] Fix test --- internal/tiger/cmd/service_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tiger/cmd/service_test.go b/internal/tiger/cmd/service_test.go index ee0a287f..264df12b 100644 --- a/internal/tiger/cmd/service_test.go +++ b/internal/tiger/cmd/service_test.go @@ -1252,7 +1252,7 @@ func TestWaitForServiceReady_Timeout(t *testing.T) { cmd.SetErr(errBuf) // Test waitForServiceReady with very short timeout to trigger timeout quickly - _, err = waitForServiceReady(client, "test-project-123", "svc-12345", 100*time.Millisecond, cmd.ErrOrStderr()) + _, err = waitForServiceReady(client, "test-project-123", "svc-12345", 100*time.Millisecond, nil, cmd.ErrOrStderr()) // Should return an error with ExitTimeout if err == nil {