WaitForReinitLoop polls the /reinit SSE endpoint in a retry loop and forwards received reinitialization events to the returned channel. The channel is closed when ctx is canceled or the server returns 409 Conflict (indicating the workspace is not a prebuilt workspace or the claim build failed perman
(ctx context.Context, logger slog.Logger, client *Client)
| 833 | // claim build failed permanently). The caller should select on both the |
| 834 | // channel and ctx.Done(). |
| 835 | func WaitForReinitLoop(ctx context.Context, logger slog.Logger, client *Client) <-chan ReinitializationEvent { |
| 836 | reinitEvents := make(chan ReinitializationEvent) |
| 837 | |
| 838 | go func() { |
| 839 | defer close(reinitEvents) |
| 840 | for retrier := retry.New(100*time.Millisecond, 10*time.Second); retrier.Wait(ctx); { |
| 841 | logger.Debug(ctx, "waiting for agent reinitialization instructions") |
| 842 | reinitEvent, err := client.WaitForReinit(ctx) |
| 843 | if err != nil { |
| 844 | var sdkErr *codersdk.Error |
| 845 | if errors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusConflict { |
| 846 | logger.Info(ctx, "received terminal 409, stopping reinit polling", |
| 847 | slog.Error(sdkErr)) |
| 848 | return |
| 849 | } |
| 850 | logger.Error(ctx, "failed to wait for agent reinitialization instructions", slog.Error(err)) |
| 851 | continue |
| 852 | } |
| 853 | retrier.Reset() |
| 854 | select { |
| 855 | case <-ctx.Done(): |
| 856 | return |
| 857 | case reinitEvents <- *reinitEvent: |
| 858 | } |
| 859 | } |
| 860 | }() |
| 861 | |
| 862 | return reinitEvents |
| 863 | } |
| 864 | |
| 865 | func NewSSEAgentReinitTransmitter(logger slog.Logger, rw http.ResponseWriter, r *http.Request) *SSEAgentReinitTransmitter { |
| 866 | return &SSEAgentReinitTransmitter{logger: logger, rw: rw, r: r} |
no test coverage detected