Skip to content

Commit

Permalink
chore(tests): retry.UntilNoError function
Browse files Browse the repository at this point in the history
- Use in `compareBlocksByNumber`
- Use in `waitForNode`
- Change `GetBlockHash` to not retry RPC
- Remove `PostWithRetry`
  • Loading branch information
qdm12 committed Apr 6, 2022
1 parent ed961e4 commit dc1d099
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 71 deletions.
18 changes: 6 additions & 12 deletions tests/stress/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/ChainSafe/gossamer/internal/log"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/tests/utils/node"
"github.com/ChainSafe/gossamer/tests/utils/retry"
"github.com/ChainSafe/gossamer/tests/utils/rpc"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -86,18 +87,11 @@ func compareBlocksByNumber(ctx context.Context, t *testing.T, nodes node.Nodes,
nodeKey: node.GetKey(),
}

for { // retry until context gets canceled
result.hash, result.err = rpc.GetBlockHash(ctx, node.GetRPCPort(), num)

if err := ctx.Err(); err != nil {
result.err = err
break
}

if result.err == nil {
break
}
}
const retryWait = 200 * time.Millisecond
result.err = retry.UntilNoError(ctx, retryWait, func() (err error) {
result.hash, err = rpc.GetBlockHash(ctx, node.GetRPCPort(), num)
return err
})

results <- result
}(n)
Expand Down
29 changes: 9 additions & 20 deletions tests/utils/node/waitnode.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,28 @@ import (
"fmt"
"time"

"github.com/ChainSafe/gossamer/tests/utils/retry"
"github.com/ChainSafe/gossamer/tests/utils/rpc"
)

func waitForNode(ctx context.Context, rpcPort string) (err error) {
tries := 0
const checkNodeStartedTimeout = time.Second
const retryWait = time.Second
for ctx.Err() == nil {
tries++

err = retry.UntilNoError(ctx, retryWait, func() (err error) {
const checkNodeStartedTimeout = time.Second
checkNodeCtx, checkNodeCancel := context.WithTimeout(ctx, checkNodeStartedTimeout)

err = checkNodeStarted(checkNodeCtx, "http://localhost:"+rpcPort)
checkNodeCancel()
if err == nil {
return nil
}
return err
})

retryWaitCtx, retryWaitCancel := context.WithTimeout(ctx, retryWait)
<-retryWaitCtx.Done()
retryWaitCancel()
if err != nil {
return fmt.Errorf("node did not start: %w", err)
}

totalTryTime := time.Duration(tries) * checkNodeStartedTimeout
tryWord := "try"
if tries > 1 {
tryWord = "tries"
}
return fmt.Errorf("node did not start after %d %s during %s: %w",
tries, tryWord, totalTryTime, err)
return nil
}

var errNodeNotExpectingPeers = errors.New("node shoult expect to have peers")
var errNodeNotExpectingPeers = errors.New("node should expect to have peers")

// checkNodeStarted check if gossamer node is started
func checkNodeStarted(ctx context.Context, gossamerHost string) error {
Expand Down
36 changes: 36 additions & 0 deletions tests/utils/retry/untilnoerror.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package retry

import (
"context"
"fmt"
"time"
)

// UntilNoError retries the function `f` until it returns a nil error.
// It waits `retryWait` after each failed call to `f`.
// If the context `ctx` is canceled, the function returns
// immediately an error stating the number of failed tries,
// for how long it retried and the last error returned by `f`.
func UntilNoError(ctx context.Context, retryWait time.Duration,
f func() (err error)) (err error) {
failedTries := 0
for ctx.Err() == nil {
err = f()
if err == nil {
return nil
}

failedTries++
waitCtx, waitCancel := context.WithTimeout(ctx, retryWait)
<-waitCtx.Done()
waitCancel()
}

totalRetryTime := time.Duration(failedTries) * retryWait
tryWord := "try"
if failedTries > 1 {
tryWord = "tries"
}
return fmt.Errorf("failed after %d %s during %s: %w (%s)",
failedTries, tryWord, totalRetryTime, err, ctx.Err())
}
4 changes: 1 addition & 3 deletions tests/utils/rpc/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"fmt"
"strconv"
"time"

"github.com/ChainSafe/gossamer/dot/rpc/modules"
"github.com/ChainSafe/gossamer/dot/types"
Expand Down Expand Up @@ -44,8 +43,7 @@ func GetBlockHash(ctx context.Context, rpcPort, num string) (hash common.Hash, e
endpoint := NewEndpoint(rpcPort)
const method = "chain_getBlockHash"
params := "[" + num + "]"
const requestWait = time.Second
respBody, err := PostWithRetry(ctx, endpoint, method, params, requestWait)
respBody, err := Post(ctx, endpoint, method, params)
if err != nil {
return hash, fmt.Errorf("cannot post RPC: %w", err)
}
Expand Down
36 changes: 0 additions & 36 deletions tests/utils/rpc/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"fmt"
"io"
"net/http"
"time"

"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
Expand Down Expand Up @@ -52,41 +51,6 @@ func Post(ctx context.Context, endpoint, method, params string) (data []byte, er
return data, nil
}

// PostWithRetry repeatitively calls `Post` repeatitively
// until it succeeds within the requestWait duration or returns
// the last error if the context is canceled.
func PostWithRetry(ctx context.Context, endpoint, method, params string,
requestWait time.Duration) (data []byte, err error) {
try := 0
for {
try++

postRPCCtx, postRPCCancel := context.WithTimeout(ctx, requestWait)

data, err = Post(postRPCCtx, endpoint, method, params)

if err == nil {
postRPCCancel()
return data, nil
}

// wait for full requestWait duration or main context cancelation
<-postRPCCtx.Done()
postRPCCancel()

if ctx.Err() != nil {
break
}
}

totalTime := time.Duration(try) * requestWait
tryWord := "try"
if try > 1 {
tryWord = "tries"
}
return nil, fmt.Errorf("after %d %s totalling %s: %w", try, tryWord, totalTime, err)
}

var (
ErrResponseVersion = errors.New("unexpected response version received")
ErrResponseError = errors.New("response error received")
Expand Down

0 comments on commit dc1d099

Please sign in to comment.