Handle retries without returning errors for non-network errors#22
Handle retries without returning errors for non-network errors#22
Conversation
|
This initial draft is meant for discussion purposes. I would be happy to discuss and revise the strategy of using different naming for the feature flags in this PR, or any suggestions. |
paymanblu
left a comment
There was a problem hiding this comment.
I am leaving some Notes for the maintainers to make it easier to follow the thought process.
| ```go | ||
| result, _ := client.GenerateText( | ||
| "meta-llama/llama-3-1-8b-instruct", | ||
| "meta-llama/llama-3-3-70b-instruct", |
There was a problem hiding this comment.
Note: the initial models seem to no longer be available by default
| elapsedTime := endTime.Sub(startTime) | ||
| expectedMinimumTime := backoffTime * time.Duration(expectedRetries) | ||
|
|
||
| if err != nil { |
There was a problem hiding this comment.
Note: The new behavior is that the error will be nil and the response will be non-nil.
This will give the user the opportunity to react to the response and use the response contents for troubleshooting purposes by logging/printing them to the end user.
pkg/models/retry.go
Outdated
|
|
||
| if !opts.retryIf(err) { | ||
| return nil, err | ||
| shouldRetry = retryConfig.retryIf(retryIfV1Err) || retryConfig.retryIfV2(resp, err) |
There was a problem hiding this comment.
Note: we call both the legacy and new retryIf for backwards compatibility purposes
pkg/models/retry.go
Outdated
|
|
||
| lastErr = err | ||
| opts.onRetry(n+1, err) | ||
| retryConfig.onRetry(n+1, statusAsErr) |
There was a problem hiding this comment.
Note: we call both the legacy and new onRetry for backwards compatibility purposes
| type HttpClient struct { | ||
| httpClient *http.Client | ||
| httpClient *http.Client | ||
| retryConfig *RetryConfig |
There was a problem hiding this comment.
Note: we add the RetryConfig to the struct as a way to influence the Client retry logic from the outside.
pkg/models/retry.go
Outdated
| type RetryIfFunc func(error) bool | ||
|
|
||
| // RetryIfFuncV2 determines whether a retry should be attempted based on the response. | ||
| type RetryIfFuncV2 func(*http.Response, error) bool |
There was a problem hiding this comment.
Note: this RetryIfV2 variation gives the user the ability to decide what they want to do based on the original response and the error. We don't coerce the status into an error prematurely as to give the user more control over the original Response and error to make a better informed decision on when to Retry.
|
Thanks @paymanblu for this contribution. Could you help let the DCO pass? Just run |
Fix Retry logic to avoid loss of request body on retry and return response body on non-200 Responses:
Issue #22
This PR addresses an issue in the
watsonx-goclient library where HTTP request bodies were being lost during retry attempts, causing 400 Bad Request errors from the server.Description
bytes.NewBuffer()for HTTP request bodies, the buffer gets consumed on the first request attempt. On subsequent retries, the request body was empty, leading to 400 HTML formatted server errors instead of expected json http responses.Code Changes
1. Enhanced Retry Mechanism (
pkg/models/retry.go)req.GetBodysupport: Enables automatic request body recreation for retries (i.e. inprepareRequest)WithRetryIfV2(): Response-based retry conditions (vs legacy error-based)WithOnRetryV2(): Enhanced retry callbacks with response accessWithReturnHTTPStatusAsErr(): Controls legacy behavior of converting HTTP status to errorsRetry(): Now expectes a request parameter for better control over the request (e.g. ability to prepare request body for retry)2. Fixed Request Body Handling (
pkg/models/generate.go,pkg/models/embedding.go)bytes.NewBuffer()withbytes.NewReader(): Prevents buffer consumption issues3. Added Test Coverage (
pkg/internal/tests/models/generate_test.go)4. Development Tools Enhancement (
Makefile)fmt-checktarget: Check code formatting without modifying filesMigration Notes
Files Modified
pkg/models/retry.go- Core retry mechanism improvementspkg/models/generate.go- Request body fix for text generationpkg/models/embedding.go- Request body fix for embeddingspkg/internal/tests/models/generate_test.go- Enhanced test coverageMakefile- Added formatting check capabilitiesExternally Visible Outcome
GenerateText err - Before fix
GenerateText err - After fix
Discussion Topics
Retryfunction and theRetryConfigare exported and visible, it is very likely that the consumers of the existing behavior will not have tried to alter the default behavior, and so we could possibly just update the code and document a migration path forward. The migration in such a case would be minimal in that the GenerateText and EmbedDocuments still return an error response as before, but the error response is just a richer response with more details.returnHTTPStatusAsErr.