Skip to content

Commit

Permalink
Configurable call timeouts and max attempts
Browse files Browse the repository at this point in the history
Adding two new CLI parameters with env variable support to configure
call timeout and max attempts after failures:

- `--call-timeout`: the time to wait for the response. This timeout is
  not enforced when downloading and uploading large streams.
  Defaults to 60.
  Can be configured using the env variable: `UIPATH_CALL_TIMEOUT`

- `--max-attempts`: the number of times to try an operation.
  Defaults to 3 times which means the operation will be retried
  up to 2 times if it fails.
  Can be configured using the env variable: `UIPATH_MAX_ATTEMPTS`
  • Loading branch information
thschmitt committed Feb 4, 2025
1 parent 8086db0 commit 2de026b
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 4 deletions.
4 changes: 4 additions & 0 deletions commandline/command_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -343,6 +345,8 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *Comm
parameters,
config.Auth,
insecure,
timeout,
maxAttempts,
debug,
*identityUri,
operation.Plugin)
Expand Down
10 changes: 10 additions & 0 deletions commandline/flag_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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),
}
}
Expand Down
23 changes: 22 additions & 1 deletion executor/execution_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package executor

import (
"net/url"
"time"

"github.com/UiPath/uipathcli/config"
"github.com/UiPath/uipathcli/plugin"
Expand All @@ -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
Expand All @@ -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,
}
}
5 changes: 2 additions & 3 deletions executor/http_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"net/url"
"runtime"
"strings"
"time"

"github.com/UiPath/uipathcli/auth"
"github.com/UiPath/uipathcli/config"
Expand Down Expand Up @@ -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)
})
}
Expand Down Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions utils/resiliency/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 2de026b

Please sign in to comment.