| index 0e4f9e625..c65d84f21 100644 |
| --- a/cmd/moveprobe/main.go |
| +++ b/cmd/moveprobe/main.go |
| @@ -224,6 +224,10 @@ type app struct { |
| workerFailed int64 |
| workerInARow int64 |
| workerLastErr string |
| + |
| + // control is the one client for the instance control socket, nil when |
| + // the agent delivered none. |
| + control *http.Client |
| } |
| |
| func openDB(path string) (*sql.DB, error) { |
| @@ -284,6 +288,14 @@ func boot(ctx context.Context, dbPath, here, from, mode string) (*app, error) { |
| return nil, err |
| } |
| a.setupStore() |
| + if sock := os.Getenv("CARLOS_CONTROL_SOCKET"); sock != "" { |
| + a.control = &http.Client{Timeout: 10 * time.Second, Transport: &http.Transport{ |
| + DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { |
| + var d net.Dialer |
| + return d.DialContext(ctx, "unix", sock) |
| + }, |
| + }} |
| + } |
| if a.storeErr == nil { |
| putCtx, cancel := context.WithTimeout(ctx, storeWait) |
| if err := a.putObject(putCtx); err != nil { |
| @@ -746,8 +758,7 @@ func (a *app) handleArmOnce(w http.ResponseWriter, r *http.Request) { |
| http.Error(w, "in: want whole seconds, at most 400 days", http.StatusBadRequest) |
| return |
| } |
| - control := os.Getenv("CARLOS_CONTROL_SOCKET") |
| - if control == "" { |
| + if a.control == nil { |
| http.Error(w, "no control socket: CARLOS_CONTROL_SOCKET is not set", http.StatusServiceUnavailable) |
| return |
| } |
| @@ -776,18 +787,16 @@ func (a *app) handleArmOnce(w http.ResponseWriter, r *http.Request) { |
| } |
| req.Header.Set("Authorization", "Bearer "+token) |
| req.Header.Set("Content-Type", "application/json") |
| - client := &http.Client{Transport: &http.Transport{ |
| - DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { |
| - var d net.Dialer |
| - return d.DialContext(ctx, "unix", control) |
| - }, |
| - }} |
| - resp, err := client.Do(req) |
| + resp, err := a.control.Do(req) |
| if err != nil { |
| http.Error(w, "control socket: "+err.Error(), http.StatusBadGateway) |
| return |
| } |
| - defer resp.Body.Close() |
| + // Drained before close, so the connection goes back for the next arm. |
| + defer func() { |
| + io.Copy(io.Discard, io.LimitReader(resp.Body, 1<<16)) |
| + resp.Body.Close() |
| + }() |
| reply, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) |
| if resp.StatusCode/100 != 2 { |
| http.Error(w, fmt.Sprintf("control socket: %d %s", resp.StatusCode, strings.TrimSpace(string(reply))), http.StatusBadGateway) |