-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Retry deploy from URL in case of errors #188
Retry deploy from URL in case of errors #188
Conversation
clients/mtaclient/mta_rest_client.go
Outdated
return AsyncUploadJobResult{ | ||
ClientActions: []string{"RETRY_UPLOAD"}, | ||
}, fmt.Errorf("could not get async file upload job %s: %s, body: %s", jobId, resp.Status, string(bodyBytes)) | ||
} | ||
return AsyncUploadJobResult{}, fmt.Errorf("could not get async file upload job %s: %s, body: %s", jobId, resp.Status, string(bodyBytes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse error message as variable
@@ -153,7 +153,7 @@ func (c RetryableMtaRestClient) GetAsyncUploadJob(jobId string, namespace *strin | |||
} | |||
resp, err := baseclient.CallWithRetry(getAsyncUploadJobCb, c.MaxRetriesCount, c.RetryInterval) | |||
if err != nil { | |||
return AsyncUploadJobResult{}, err | |||
return resp.(AsyncUploadJobResult), err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why resp
object must be returned now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we can re-use the retry logic:
if resp.StatusCode == 400 { return AsyncUploadJobResult{ ClientActions: []string{"RETRY_UPLOAD"}, }, fmt.Errorf("%s %s: %s, body: %s", couldNotGetAsyncJobError, jobId, resp.Status, string(bodyBytes)) }
In this code the retry is explicitly set and it will be wiped out if we just return an empty object in the retryable client
commands/deploy_command.go
Outdated
for i := 0; i < 3; i++ { | ||
progressBar := c.tryFetchMtarSize(url, disableProgressBar) | ||
uploadFromUrlStatus = c.doUploadFromUrl(encodedFileUrl, mtaClient, namespace, progressBar) | ||
if shouldRetryUpload(uploadFromUrlStatus) { | ||
ui.Warn("Retrying failed upload from URL operation") | ||
continue | ||
} | ||
return uploadFromUrlStatus | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we use some general retry mechanism? This custom retry logic is not configurable via --retries
command flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored it a bit, so it could be reused. We cannot reuse the other retries, as one is bound to the rest client and the other retries the MTA operation.
Do you think this retry logic should be bound to the --retries, imo it should be used only for retrying the operation, not the upload.
It will be inconsistent to use --retries here, because in the regular upload, there are 3 retries hardcoded
commands/deploy_command.go
Outdated
func shouldRetryUpload(uploadFromUrlStatus UploadFromUrlStatus) bool { | ||
if uploadFromUrlStatus.ExecutionStatus == Success { | ||
return false | ||
} | ||
for _, clientAction := range uploadFromUrlStatus.ClientActions { | ||
if clientAction == "RETRY_UPLOAD" { | ||
return true | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have similar retry mechanism when upload file to the backend of deploy-service?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there's a single request/response, which will be retried by the rest client retry mechanism
6ca6993
to
b6dfe07
Compare
commands/retrier/retry_util.go
Outdated
time.Sleep(3 * time.Second) | ||
continue | ||
} | ||
return result, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we return err
variable instead nil? This way error won't be consumed in this function and will be propagated in the caller function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, fixed
"github.com/cloudfoundry-incubator/multiapps-cli-plugin/log" | ||
) | ||
|
||
func Execute[T any](attempts int, callback func() (T, error), shouldRetry func(result T, err error) bool) (T, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really cool
b6dfe07
to
e1d7c7a
Compare
e1d7c7a
to
fdee666
Compare
|
||
func logError[T any](result T, err error) { | ||
if err != nil { | ||
log.Tracef("retrying an operation that failed with: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
intentionally lowercase
No description provided.