Skip to content

Commit

Permalink
chore: Remove SendWithRetry
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurpitman committed Aug 21, 2024
1 parent dbb8576 commit 957e281
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 177 deletions.
44 changes: 25 additions & 19 deletions pkg/client/dtclient/config_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,43 +275,49 @@ func (d *DynatraceClient) callWithRetryOnKnowTimingIssue(ctx context.Context, re
return resp, nil
}

apiError := coreapi.APIError{}
if !errors.As(err, &apiError) {
apiErr := coreapi.APIError{}
if !errors.As(err, &apiErr) {
return nil, err
}

var rs RetrySetting
rs := selectRetrySettingByAPIAndAPIError(d.retrySettings, theApi, apiErr)
if rs.MaxRetries == 0 {
return resp, err
}

return coreapi.AsResponseOrError(restCall(ctx, endpoint, bytes.NewReader(requestBody), corerest.RequestOptions{ /* WITH RETRY SETTINGS HERE */ }))
}

func selectRetrySettingByAPIAndAPIError(retrySettings RetrySettings, theAPI api.API, apiErr coreapi.APIError) RetrySetting {
rs := RetrySetting{}

// It can take longer until calculated service metrics are ready to be used in SLOs
if isCalculatedMetricNotReadyYet(apiError) ||
if isCalculatedMetricNotReadyYet(apiErr) ||
// It can take longer until management zones are ready to be used in SLOs
isManagementZoneNotReadyYet(apiError) ||
isManagementZoneNotReadyYet(apiErr) ||
// It can take longer until Credentials are ready to be used in Synthetic Monitors
isCredentialNotReadyYet(apiError) ||
isCredentialNotReadyYet(apiErr) ||
// It can take some time for configurations to propagate to all cluster nodes - indicated by an incorrect constraint violation error
isGeneralDependencyNotReadyYet(apiError) ||
isGeneralDependencyNotReadyYet(apiErr) ||
// Synthetic and related APIs sometimes run into issues of finding objects quickly after creation
isGeneralSyntheticAPIError(apiError, theApi) ||
isGeneralSyntheticAPIError(apiErr, theAPI) ||
// Network zone deployments can fail due to fact that the feature not effectively enabled yet
isNetworkZoneFeatureNotEnabledYet(apiError, theApi) {
isNetworkZoneFeatureNotEnabledYet(apiErr, theAPI) {

rs = d.retrySettings.Normal
rs = retrySettings.Normal
}

// It can take even longer until request attributes are ready to be used
if isRequestAttributeNotYetReady(apiError) {
rs = d.retrySettings.Long
if isRequestAttributeNotYetReady(apiErr) {
rs = retrySettings.Long
}

// It can take even longer until applications are ready to be used in synthetic tests and calculated metrics
if isApplicationNotReadyYet(apiError, theApi) {
rs = d.retrySettings.VeryLong
}

if rs.MaxRetries > 0 {
return SendWithRetry(ctx, restCall, endpoint, corerest.RequestOptions{}, requestBody, rs)
if isApplicationNotReadyYet(apiErr, theAPI) {
rs = retrySettings.VeryLong
}

return resp, err
return rs
}

func isGeneralDependencyNotReadyYet(apiError coreapi.APIError) bool {
Expand Down
46 changes: 2 additions & 44 deletions pkg/client/dtclient/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,12 @@
package dtclient

import (
"bytes"
"context"
"errors"
"fmt"

corerest "github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
"io"
"net/http"
"time"

coreapi "github.com/dynatrace/dynatrace-configuration-as-code-core/api"
corerest "github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/internal/log"
)

type RetrySetting struct {
Expand Down Expand Up @@ -58,40 +53,3 @@ var DefaultRetrySettings = RetrySettings{

// SendRequestWithBody is a function doing a PUT or POST HTTP request
type SendRequestWithBody func(ctx context.Context, endpoint string, body io.Reader, options corerest.RequestOptions) (*http.Response, error)

// SendWithRetry will retry to call sendWithBody for a given number of times, waiting a give duration between calls
func SendWithRetry(ctx context.Context, sendWithBody SendRequestWithBody, endpoint string, requestOptions corerest.RequestOptions, body []byte, setting RetrySetting) (*coreapi.Response, error) {
var err error
var resp *coreapi.Response

for i := 0; i < setting.MaxRetries; i++ {
log.WithCtxFields(ctx).Warn("Failed to send HTTP request. Waiting for %s before retrying...", setting.WaitTime)
time.Sleep(setting.WaitTime)
resp, err = coreapi.AsResponseOrError(sendWithBody(ctx, endpoint, bytes.NewReader(body), requestOptions))
if err == nil {
return resp, nil
}

apierror := coreapi.APIError{}
if !errors.As(err, &apierror) {
return nil, err
}
}

return nil, fmt.Errorf("HTTP send request %s failed after %d retries: %w", endpoint, setting.MaxRetries, err)
}

// SendWithRetryWithInitialTry will try to call sendWithBody and if it didn't succeed call [SendWithRetry]
func SendWithRetryWithInitialTry(ctx context.Context, sendWithBody SendRequestWithBody, endpoint string, requestOptions corerest.RequestOptions, body []byte, setting RetrySetting) (*coreapi.Response, error) {
resp, err := coreapi.AsResponseOrError(sendWithBody(ctx, endpoint, bytes.NewReader(body), requestOptions))
if err == nil {
return resp, nil
}

apierror := coreapi.APIError{}
if !errors.As(err, &apierror) {
return nil, err
}

return SendWithRetry(ctx, sendWithBody, endpoint, requestOptions, body, setting)
}
113 changes: 0 additions & 113 deletions pkg/client/dtclient/retry_test.go

This file was deleted.

8 changes: 7 additions & 1 deletion pkg/client/dtclient/settings_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,13 @@ func (d *DynatraceClient) UpsertSettings(ctx context.Context, obj SettingsObject
retrySetting = d.retrySettings.Normal
}

resp, err := SendWithRetryWithInitialTry(ctx, d.platformClient.POST, d.settingsObjectAPIPath, corerest.RequestOptions{}, payload, retrySetting)
requestRetrier := corerest.RequestRetrier{
MaxRetries: retrySetting.MaxRetries,
DelayAfterRetry: retrySetting.WaitTime,
ShouldRetryFunc: corerest.RetryIfNotSuccess,
}

resp, err := coreapi.AsResponseOrError(d.platformClient.POST(ctx, d.settingsObjectAPIPath, bytes.NewReader(payload), corerest.RequestOptions{CustomRetrier: &requestRetrier}))
if err != nil {
d.settingsCache.Delete(obj.SchemaId)
return DynatraceEntity{}, fmt.Errorf("failed to create or update Settings object with externalId %s: %w", externalID, err)
Expand Down

0 comments on commit 957e281

Please sign in to comment.