|
8 | 8 | "io" |
9 | 9 | "net/http" |
10 | 10 | "net/url" |
| 11 | + "strings" |
11 | 12 | "time" |
12 | 13 |
|
13 | 14 | "github.com/veertuinc/anka-cloud-gitlab-executor/internal/gitlab" |
@@ -77,7 +78,25 @@ func (c *APIClient) Post(ctx context.Context, endpoint string, payload interface |
77 | 78 |
|
78 | 79 | bodyBytes, err := io.ReadAll(r.Body) |
79 | 80 | if err != nil { |
80 | | - return nil, fmt.Errorf("failed to read response body: %w", err) |
| 81 | + if strings.Contains(err.Error(), "unexpected EOF") { |
| 82 | + // Retry once on unexpected EOF |
| 83 | + r2, err2 := c.HttpClient.Do(req) |
| 84 | + if err2 != nil { |
| 85 | + if e, ok := err2.(*url.Error); ok && e.Timeout() { |
| 86 | + return nil, gitlab.TransientError(fmt.Errorf("failed to send POST request to %s with payload %+v (retry): %w", endpointUrl, payload, e)) |
| 87 | + } |
| 88 | + return nil, fmt.Errorf("failed to send POST request to %s with payload %+v (retry): %w", endpoint, payload, err2) |
| 89 | + } |
| 90 | + defer r2.Body.Close() |
| 91 | + |
| 92 | + bodyBytes, err2 = io.ReadAll(r2.Body) |
| 93 | + if err2 != nil { |
| 94 | + return nil, fmt.Errorf("failed to read response body (retry): %w", err2) |
| 95 | + } |
| 96 | + r = r2 |
| 97 | + } else { |
| 98 | + return nil, fmt.Errorf("failed to read response body: %w", err) |
| 99 | + } |
81 | 100 | } |
82 | 101 |
|
83 | 102 | baseResponse, err := c.parse(bodyBytes) |
@@ -123,7 +142,25 @@ func (c *APIClient) Delete(ctx context.Context, endpoint string, payload interfa |
123 | 142 |
|
124 | 143 | bodyBytes, err := io.ReadAll(r.Body) |
125 | 144 | if err != nil { |
126 | | - return nil, fmt.Errorf("failed to read response body: %w", err) |
| 145 | + if strings.Contains(err.Error(), "unexpected EOF") { |
| 146 | + // Retry once on unexpected EOF |
| 147 | + r2, err2 := c.HttpClient.Do(req) |
| 148 | + if err2 != nil { |
| 149 | + if e, ok := err2.(*url.Error); ok && e.Timeout() { |
| 150 | + return nil, gitlab.TransientError(fmt.Errorf("failed to send DELETE request to %s with payload %+v (retry): %w", endpointUrl, payload, e)) |
| 151 | + } |
| 152 | + return nil, fmt.Errorf("failed to send DELETE request to %s with payload %+v (retry): %w", endpoint, payload, err2) |
| 153 | + } |
| 154 | + defer r2.Body.Close() |
| 155 | + |
| 156 | + bodyBytes, err2 = io.ReadAll(r2.Body) |
| 157 | + if err2 != nil { |
| 158 | + return nil, fmt.Errorf("failed to read response body (retry): %w", err2) |
| 159 | + } |
| 160 | + r = r2 |
| 161 | + } else { |
| 162 | + return nil, fmt.Errorf("failed to read response body: %w", err) |
| 163 | + } |
127 | 164 | } |
128 | 165 |
|
129 | 166 | baseResponse, err := c.parse(bodyBytes) |
@@ -166,7 +203,25 @@ func (c *APIClient) Get(ctx context.Context, endpoint string, queryParams map[st |
166 | 203 |
|
167 | 204 | bodyBytes, err := io.ReadAll(r.Body) |
168 | 205 | if err != nil { |
169 | | - return nil, fmt.Errorf("failed to read response body: %w", err) |
| 206 | + if strings.Contains(err.Error(), "unexpected EOF") { |
| 207 | + // Retry once on unexpected EOF |
| 208 | + r2, err2 := c.HttpClient.Do(req) |
| 209 | + if err2 != nil { |
| 210 | + if e, ok := err2.(*url.Error); ok && e.Timeout() { |
| 211 | + return nil, gitlab.TransientError(fmt.Errorf("failed to send GET request to %s (retry): %w", endpointUrl, e)) |
| 212 | + } |
| 213 | + return nil, fmt.Errorf("failed to send GET request to %s (retry): %w", endpointUrl, err2) |
| 214 | + } |
| 215 | + defer r2.Body.Close() |
| 216 | + |
| 217 | + bodyBytes, err2 = io.ReadAll(r2.Body) |
| 218 | + if err2 != nil { |
| 219 | + return nil, fmt.Errorf("failed to read response body (retry): %w", err2) |
| 220 | + } |
| 221 | + r = r2 |
| 222 | + } else { |
| 223 | + return nil, fmt.Errorf("failed to read response body: %w", err) |
| 224 | + } |
170 | 225 | } |
171 | 226 |
|
172 | 227 | baseResponse, err := c.parse(bodyBytes) |
|
0 commit comments