Skip to content

Commit

Permalink
fix: client default timeout (#310)
Browse files Browse the repository at this point in the history
* fix: client default timeout #259

Signed-off-by: Ceres Cheng <chengzhoukun@gmail.com>

* Add documentation for client timeout environment variable

Signed-off-by: Ceres Cheng <chengzhoukun@gmail.com>
  • Loading branch information
zhoukuncheng authored Aug 5, 2022
1 parent c4217cf commit 7c38f5a
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 10 deletions.
21 changes: 21 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,27 @@ func main() {
}
```

`NewClient` function has a default timeout for 5s, but you can customize this timeout by setting the environment variable `DAPR_CLIENT_TIMEOUT_SECONDS`.
For example:
```go
package main

import (
"os"

dapr "github.com/dapr/go-sdk/client"
)

func main() {
os.Setenv("DAPR_CLIENT_TIMEOUT_SECONDS", "3")
client, err := dapr.NewClient()
if err != nil {
panic(err)
}
defer client.Close()
}
```

Assuming you have [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr/) installed, you can then launch your app locally like this:

```shell
Expand Down
43 changes: 33 additions & 10 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"log"
"net"
"os"
"strconv"
"sync"
"time"

Expand All @@ -38,11 +39,13 @@ import (
)

const (
daprPortDefault = "50001"
daprPortEnvVarName = "DAPR_GRPC_PORT" /* #nosec */
traceparentKey = "traceparent"
apiTokenKey = "dapr-api-token" /* #nosec */
apiTokenEnvVarName = "DAPR_API_TOKEN" /* #nosec */
daprPortDefault = "50001"
daprPortEnvVarName = "DAPR_GRPC_PORT" /* #nosec */
traceparentKey = "traceparent"
apiTokenKey = "dapr-api-token" /* #nosec */
apiTokenEnvVarName = "DAPR_API_TOKEN" /* #nosec */
clientDefaultTimoutSeconds = 5
clientTimoutSecondsEnvVarName = "DAPR_CLIENT_TIMEOUT_SECONDS"
)

var (
Expand Down Expand Up @@ -182,10 +185,11 @@ type Client interface {
// Note, this default factory function creates Dapr client only once. All subsequent invocations
// will return the already created instance. To create multiple instances of the Dapr client,
// use one of the parameterized factory functions:
// NewClientWithPort(port string) (client Client, err error)
// NewClientWithAddress(address string) (client Client, err error)
// NewClientWithConnection(conn *grpc.ClientConn) Client
// NewClientWithSocket(socket string) (client Client, err error)
//
// NewClientWithPort(port string) (client Client, err error)
// NewClientWithAddress(address string) (client Client, err error)
// NewClientWithConnection(conn *grpc.ClientConn) Client
// NewClientWithSocket(socket string) (client Client, err error)
func NewClient() (client Client, err error) {
port := os.Getenv(daprPortEnvVarName)
if port == "" {
Expand Down Expand Up @@ -216,7 +220,11 @@ func NewClientWithAddress(address string) (client Client, err error) {
}
logger.Printf("dapr client initializing for: %s", address)

ctx, ctxCancel := context.WithTimeout(context.Background(), 1*time.Second)
timeoutSeconds, err := getClientTimeoutSeconds()
if err != nil {
return nil, err
}
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Duration(timeoutSeconds)*time.Second)
conn, err := grpc.DialContext(
ctx,
address,
Expand All @@ -234,6 +242,21 @@ func NewClientWithAddress(address string) (client Client, err error) {
return newClientWithConnectionAndCancelFunc(conn, ctxCancel), nil
}

func getClientTimeoutSeconds() (int, error) {
timeoutStr := os.Getenv(clientTimoutSecondsEnvVarName)
if len(timeoutStr) == 0 {
return clientDefaultTimoutSeconds, nil
}
timeoutVar, err := strconv.Atoi(timeoutStr)
if err != nil {
return 0, err
}
if timeoutVar <= 0 {
return 0, errors.New("incorrect value")
}
return timeoutVar, nil
}

// NewClientWithSocket instantiates Dapr using specific socket.
func NewClientWithSocket(socket string) (client Client, err error) {
if socket == "" {
Expand Down
34 changes: 34 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,40 @@ func getTestClientWithSocket(ctx context.Context) (client Client, closer func())
return
}

func Test_getClientTimeoutSeconds(t *testing.T) {
t.Run("empty env var", func(t *testing.T) {
os.Setenv(clientTimoutSecondsEnvVarName, "")
got, err := getClientTimeoutSeconds()
assert.NoError(t, err)
assert.Equal(t, clientDefaultTimoutSeconds, got)
})

t.Run("invalid env var", func(t *testing.T) {
os.Setenv(clientTimoutSecondsEnvVarName, "invalid")
_, err := getClientTimeoutSeconds()
assert.Error(t, err)
})

t.Run("normal env var", func(t *testing.T) {
os.Setenv(clientTimoutSecondsEnvVarName, "7")
got, err := getClientTimeoutSeconds()
assert.NoError(t, err)
assert.Equal(t, 7, got)
})

t.Run("zero env var", func(t *testing.T) {
os.Setenv(clientTimoutSecondsEnvVarName, "0")
_, err := getClientTimeoutSeconds()
assert.Error(t, err)
})

t.Run("negative env var", func(t *testing.T) {
os.Setenv(clientTimoutSecondsEnvVarName, "-3")
_, err := getClientTimeoutSeconds()
assert.Error(t, err)
})
}

type testDaprServer struct {
pb.UnimplementedDaprServer
state map[string][]byte
Expand Down

0 comments on commit 7c38f5a

Please sign in to comment.