waitUntilCodespaceConnectionReady waits for a Codespace to be running and is able to be connected to.
(ctx context.Context, progress progressIndicator, apiClient apiClient, codespace *api.Codespace)
| 76 | |
| 77 | // waitUntilCodespaceConnectionReady waits for a Codespace to be running and is able to be connected to. |
| 78 | func waitUntilCodespaceConnectionReady(ctx context.Context, progress progressIndicator, apiClient apiClient, codespace *api.Codespace) (*api.Codespace, error) { |
| 79 | if connectionReady(codespace) { |
| 80 | return codespace, nil |
| 81 | } |
| 82 | |
| 83 | progress.StartProgressIndicatorWithLabel("Waiting for codespace to become ready") |
| 84 | defer progress.StopProgressIndicator() |
| 85 | |
| 86 | lastState := "" |
| 87 | firstRetry := true |
| 88 | |
| 89 | err := backoff.Retry(func() error { |
| 90 | var err error |
| 91 | if firstRetry { |
| 92 | firstRetry = false |
| 93 | } else { |
| 94 | codespace, err = apiClient.GetCodespace(ctx, codespace.Name, true) |
| 95 | if err != nil { |
| 96 | return backoff.Permanent(fmt.Errorf("error getting codespace: %w", err)) |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | if connectionReady(codespace) { |
| 101 | return nil |
| 102 | } |
| 103 | |
| 104 | // Only react to changes in the state (so that we don't try to start the codespace twice) |
| 105 | if codespace.State != lastState { |
| 106 | if codespace.State == api.CodespaceStateShutdown { |
| 107 | err = apiClient.StartCodespace(ctx, codespace.Name) |
| 108 | if err != nil { |
| 109 | return backoff.Permanent(fmt.Errorf("error starting codespace: %w", err)) |
| 110 | } |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | lastState = codespace.State |
| 115 | |
| 116 | return &TimeoutError{message: "codespace not ready yet"} |
| 117 | }, backoff.WithContext(codespaceStatePollingBackoff, ctx)) |
| 118 | |
| 119 | if err != nil { |
| 120 | var timeoutErr *TimeoutError |
| 121 | if errors.As(err, &timeoutErr) { |
| 122 | return nil, errors.New("timed out while waiting for the codespace to start") |
| 123 | } |
| 124 | |
| 125 | return nil, err |
| 126 | } |
| 127 | |
| 128 | return codespace, nil |
| 129 | } |
| 130 | |
| 131 | // ListenTCP starts a localhost tcp listener on 127.0.0.1 (unless allInterfaces is true) and returns the listener and bound port |
| 132 | func ListenTCP(port int, allInterfaces bool) (*net.TCPListener, int, error) { |