Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 1dce66b

Browse files
committed
[FAB-10712] Add BeforeRetry callback to Channel Client
The use case for this is to maintain application level metrics on how many retry attempts are made by the sdk Change-Id: Ic2b6ae578a8ddf95e0ee4586130082c8812ae667 Signed-off-by: Divyank Katira <Divyank.Katira@securekey.com>
1 parent 0bb0a3f commit 1dce66b

File tree

4 files changed

+28
-0
lines changed

4 files changed

+28
-0
lines changed

pkg/client/channel/api.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type requestOptions struct {
2323
Targets []fab.Peer // targets
2424
TargetFilter fab.TargetFilter
2525
Retry retry.Opts
26+
BeforeRetry retry.BeforeRetryHandler
2627
Timeouts map[fab.TimeoutType]time.Duration //timeout options for channel client operations
2728
ParentContext reqContext.Context //parent grpc context for channel client operations (query, execute, invokehandler)
2829
}
@@ -107,6 +108,14 @@ func WithRetry(retryOpt retry.Opts) RequestOption {
107108
}
108109
}
109110

111+
// WithBeforeRetry specifies a function to call before a retry attempt
112+
func WithBeforeRetry(beforeRetry retry.BeforeRetryHandler) RequestOption {
113+
return func(ctx context.Client, o *requestOptions) error {
114+
o.BeforeRetry = beforeRetry
115+
return nil
116+
}
117+
}
118+
110119
//WithTimeout encapsulates key value pairs of timeout type, timeout duration to Options
111120
func WithTimeout(timeoutType fab.TimeoutType, timeout time.Duration) RequestOption {
112121
return func(ctx context.Client, o *requestOptions) error {

pkg/client/channel/chclient.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ func (cc *Client) InvokeHandler(handler invoke.Handler, request Request, options
163163
requestContext.RetryHandler,
164164
retry.WithBeforeRetry(
165165
func(err error) {
166+
if requestContext.Opts.BeforeRetry != nil {
167+
requestContext.Opts.BeforeRetry(err)
168+
}
169+
166170
cc.greylist.Greylist(err)
167171

168172
// Reset context parameters

pkg/client/channel/chclient_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,20 @@ func TestExecuteTxWithRetries(t *testing.T) {
433433
assert.Equal(t, testResp, resp.Payload, "expected correct response")
434434
}
435435

436+
func TestBeforeRetryOption(t *testing.T) {
437+
testStatus := status.New(status.EndorserClientStatus, status.ConnectionFailed.ToInt32(), "test", nil)
438+
439+
testPeer1 := fcmocks.NewMockPeer("Peer1", "http://peer1.com")
440+
testPeer1.Error = testStatus
441+
chClient := setupChannelClient([]fab.Peer{testPeer1}, t)
442+
443+
var callbacks int
444+
445+
_, _ = chClient.Query(Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("query"), []byte("b")}},
446+
WithRetry(retry.DefaultChannelOpts), WithBeforeRetry(func(error) { callbacks++ }))
447+
assert.Equal(t, retry.DefaultChannelOpts.Attempts, callbacks, "Expected callback on each attempt")
448+
}
449+
436450
func TestMultiErrorPropogation(t *testing.T) {
437451
testErr := fmt.Errorf("Test Error")
438452

pkg/client/channel/invoke/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Opts struct {
2323
Targets []fab.Peer // targets
2424
TargetFilter fab.TargetFilter
2525
Retry retry.Opts
26+
BeforeRetry retry.BeforeRetryHandler
2627
Timeouts map[fab.TimeoutType]time.Duration
2728
ParentContext reqContext.Context //parent grpc context
2829
}

0 commit comments

Comments
 (0)