diff --git a/commandline/command_builder.go b/commandline/command_builder.go index d36774d..e59b1aa 100644 --- a/commandline/command_builder.go +++ b/commandline/command_builder.go @@ -326,6 +326,8 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *Comm tenant = config.Tenant } insecure := context.Bool(FlagNameInsecure) || config.Insecure + timeout := time.Duration(context.Int(FlagNameCallTimeout)) * time.Second + maxAttempts := context.Int(FlagNameMaxAttempts) debug := context.Bool(FlagNameDebug) || config.Debug identityUri, err := b.createIdentityUri(context, *config, baseUri) if err != nil { @@ -343,6 +345,8 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *Comm parameters, config.Auth, insecure, + timeout, + maxAttempts, debug, *identityUri, operation.Plugin) diff --git a/commandline/flag_builder.go b/commandline/flag_builder.go index 2835a33..f9cd2dc 100644 --- a/commandline/flag_builder.go +++ b/commandline/flag_builder.go @@ -21,6 +21,8 @@ const FlagNameIdentityUri = "identity-uri" const FlagNameServiceVersion = "service-version" const FlagNameHelp = "help" const FlagNameVersion = "version" +const FlagNameCallTimeout = "call-timeout" +const FlagNameMaxAttempts = "max-attempts" const FlagValueFromStdIn = "-" const FlagValueOutputFormatJson = "json" @@ -137,6 +139,14 @@ func (b FlagBuilder) defaultFlags(hidden bool) []*FlagDefinition { NewFlag(FlagNameIdentityUri, "Identity Server URI", FlagTypeString). WithEnvVarName("UIPATH_IDENTITY_URI"). WithHidden(hidden), + NewFlag(FlagNameCallTimeout, "Call Timeout", FlagTypeInteger). + WithEnvVarName("UIPATH_CALL_TIMEOUT"). + WithDefaultValue(60). + WithHidden(true), + NewFlag(FlagNameMaxAttempts, "Max Attempts", FlagTypeInteger). + WithEnvVarName("UIPATH_MAX_ATTEMPTS"). + WithDefaultValue(3). + WithHidden(true), b.serviceVersionFlag(hidden), } } diff --git a/executor/execution_context.go b/executor/execution_context.go index 8fbcbae..1abb0a8 100644 --- a/executor/execution_context.go +++ b/executor/execution_context.go @@ -2,6 +2,7 @@ package executor import ( "net/url" + "time" "github.com/UiPath/uipathcli/config" "github.com/UiPath/uipathcli/plugin" @@ -21,6 +22,8 @@ type ExecutionContext struct { Parameters ExecutionParameters AuthConfig config.AuthConfig Insecure bool + Timeout time.Duration + MaxAttempts int Debug bool IdentityUri url.URL Plugin plugin.CommandPlugin @@ -37,8 +40,26 @@ func NewExecutionContext( parameters []ExecutionParameter, authConfig config.AuthConfig, insecure bool, + timeout time.Duration, + maxAttempts int, debug bool, identityUri url.URL, plugin plugin.CommandPlugin) *ExecutionContext { - return &ExecutionContext{organization, tenant, method, uri, route, contentType, input, parameters, authConfig, insecure, debug, identityUri, plugin} + return &ExecutionContext{ + organization, + tenant, + method, + uri, + route, + contentType, + input, + parameters, + authConfig, + insecure, + timeout, + maxAttempts, + debug, + identityUri, + plugin, + } } diff --git a/executor/http_executor.go b/executor/http_executor.go index 91d8376..819c3e1 100644 --- a/executor/http_executor.go +++ b/executor/http_executor.go @@ -13,7 +13,6 @@ import ( "net/url" "runtime" "strings" - "time" "github.com/UiPath/uipathcli/auth" "github.com/UiPath/uipathcli/config" @@ -44,7 +43,7 @@ type HttpExecutor struct { } func (e HttpExecutor) Call(context ExecutionContext, writer output.OutputWriter, logger log.Logger) error { - return resiliency.Retry(func() error { + return resiliency.RetryN(context.MaxAttempts, func() error { return e.call(context, writer, logger) }) } @@ -345,7 +344,7 @@ func (e HttpExecutor) call(context ExecutionContext, writer output.OutputWriter, transport := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: context.Insecure}, //nolint // This is user configurable and disabled by default - ResponseHeaderTimeout: 60 * time.Second, + ResponseHeaderTimeout: context.Timeout, } client := &http.Client{Transport: transport} if context.Debug { diff --git a/utils/resiliency/retry.go b/utils/resiliency/retry.go index 9fd9ec9..0827cdd 100644 --- a/utils/resiliency/retry.go +++ b/utils/resiliency/retry.go @@ -8,6 +8,11 @@ const MaxAttempts = 3 // Retries the given function up to 3 times when it returns an RetryableError. func Retry(f func() error) error { + return RetryN(MaxAttempts, f) +} + +// Retries the given function up to n times when it returns an RetryableError. +func RetryN(maxAttempts int, f func() error) error { var err error for i := 1; ; i++ { err = f()