| 134 | } |
| 135 | |
| 136 | func waitForDisco(ctx context.Context, logs io.Writer, conn workspacesdk.AgentConn) error { |
| 137 | const pingAttempts = 10 |
| 138 | const pingDelay = 1 * time.Second |
| 139 | |
| 140 | ctx, span := tracing.StartSpan(ctx) |
| 141 | defer span.End() |
| 142 | |
| 143 | for i := 0; i < pingAttempts; i++ { |
| 144 | _, _ = fmt.Fprintf(logs, "\tDisco ping attempt %d/%d...\n", i+1, pingAttempts) |
| 145 | pingCtx, cancel := context.WithTimeout(ctx, defaultRequestTimeout) |
| 146 | _, p2p, _, err := conn.Ping(pingCtx) |
| 147 | cancel() |
| 148 | if err == nil { |
| 149 | _, _ = fmt.Fprintf(logs, "\tDisco ping succeeded after %d attempts, p2p = %v\n", i+1, p2p) |
| 150 | break |
| 151 | } |
| 152 | if i == pingAttempts-1 { |
| 153 | return xerrors.Errorf("ping workspace agent: %w", err) |
| 154 | } |
| 155 | |
| 156 | select { |
| 157 | case <-ctx.Done(): |
| 158 | return xerrors.Errorf("wait for connection to be established: %w", ctx.Err()) |
| 159 | // We use time.After here since it's a very short duration so leaking a |
| 160 | // timer is fine. |
| 161 | case <-time.After(pingDelay): |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | return nil |
| 166 | } |
| 167 | |
| 168 | func waitForDirectConnection(ctx context.Context, logs io.Writer, conn workspacesdk.AgentConn) error { |
| 169 | const directConnectionAttempts = 30 |