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

Commit b447674

Browse files
troyrondaGerrit Code Review
authored andcommitted
Merge "[FAB-8261] Introduce Multi Errors type"
2 parents 786e8c5 + 39a4250 commit b447674

File tree

29 files changed

+374
-365
lines changed

29 files changed

+374
-365
lines changed

api/apifabclient/mocks/mockfabclient.gen.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/apifabclient/proposer.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// ProposalProcessor simulates transaction proposal, so that a client can submit the result for ordering.
1414
type ProposalProcessor interface {
15-
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResult, error)
15+
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResponse, error)
1616
}
1717

1818
// ProposalSender provides the ability for a transaction proposal to be created and sent.
@@ -43,19 +43,11 @@ type TransactionProposal struct {
4343
Proposal *pb.Proposal
4444
}
4545

46-
// TransactionProposalResponse encapsulates both the result of transaction proposal processing and errors.
46+
// TransactionProposalResponse respresents the result of transaction proposal processing.
4747
type TransactionProposalResponse struct {
48-
TransactionProposalResult
49-
Err error // TODO: consider refactoring
50-
}
51-
52-
// TransactionProposalResult respresents the result of transaction proposal processing.
53-
type TransactionProposalResult struct {
5448
Endorser string
5549
Status int32
5650

5751
Proposal TransactionProposal
5852
ProposalResponse *pb.ProposalResponse
5953
}
60-
61-
// TODO: TransactionProposalResponse and TransactionProposalResult may need better names.

api/apitxn/resmgmtclient/resmgmt.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ type InstallCCResponse struct {
3232
Target string
3333
Status int32
3434
Info string
35-
Err error
3635
}
3736

3837
// InstantiateCCRequest contains instantiate chaincode request parameters

pkg/errors/multi/multi.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package multi
8+
9+
import (
10+
"fmt"
11+
"strings"
12+
)
13+
14+
// Errors is used to represent multiple errors
15+
type Errors []error
16+
17+
// New Errors object with the given errors. Only non-nil errors are added.
18+
func New(errs ...error) error {
19+
errors := Errors{}
20+
for _, err := range errs {
21+
if err != nil {
22+
errors = append(errors, err)
23+
}
24+
}
25+
26+
if len(errors) == 0 {
27+
return nil
28+
}
29+
30+
if len(errors) == 1 {
31+
return errors[0]
32+
}
33+
34+
return errors
35+
}
36+
37+
// Append error to Errors. If the first arg is not an Errors object, one will be created
38+
func Append(errs error, err error) error {
39+
m, ok := errs.(Errors)
40+
if !ok {
41+
return New(errs, err)
42+
}
43+
return append(m, err)
44+
}
45+
46+
// ToError converts Errors to the error interface
47+
// returns nil if no errors are present, a single error object if only one is present
48+
func (errs Errors) ToError() error {
49+
if len(errs) == 0 {
50+
return nil
51+
}
52+
if len(errs) == 1 {
53+
return errs[0]
54+
}
55+
return errs
56+
}
57+
58+
// Error implements the error interface to return a string representation of Errors
59+
func (errs Errors) Error() string {
60+
if len(errs) == 0 {
61+
return ""
62+
}
63+
if len(errs) == 1 {
64+
return errs[0].Error()
65+
}
66+
67+
errors := []string{fmt.Sprint("Multiple errors occurred: ")}
68+
for _, err := range errs {
69+
errors = append(errors, err.Error())
70+
}
71+
return strings.Join(errors, "\n")
72+
}

pkg/errors/multi/multi_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package multi
8+
9+
import (
10+
"fmt"
11+
"testing"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestErrorString(t *testing.T) {
17+
testErr := fmt.Errorf("test")
18+
var errs Errors
19+
20+
assert.Equal(t, "", errs.Error())
21+
22+
errs = append(errs, testErr)
23+
assert.Equal(t, testErr.Error(), errs.Error())
24+
25+
errs = append(errs, testErr)
26+
assert.Equal(t, "Multiple errors occurred: \ntest\ntest", errs.Error())
27+
}
28+
29+
func TestAppend(t *testing.T) {
30+
testErr := fmt.Errorf("test")
31+
testErr2 := fmt.Errorf("test2")
32+
33+
m := Append(nil, nil)
34+
assert.Nil(t, m)
35+
36+
m = Append(nil, testErr)
37+
assert.Equal(t, testErr, m)
38+
39+
m = Append(testErr, testErr2)
40+
m1, ok := m.(Errors)
41+
assert.True(t, ok)
42+
assert.Equal(t, testErr, m1[0])
43+
assert.Equal(t, testErr2, m1[1])
44+
45+
m = Append(Errors{testErr}, testErr2)
46+
m1, ok = m.(Errors)
47+
assert.True(t, ok)
48+
assert.Equal(t, testErr, m1[0])
49+
assert.Equal(t, testErr2, m1[1])
50+
}
51+
52+
func TestToError(t *testing.T) {
53+
testErr := fmt.Errorf("test")
54+
var errs Errors
55+
56+
assert.Equal(t, nil, errs.ToError())
57+
58+
errs = append(errs, testErr)
59+
assert.Equal(t, testErr, errs.ToError())
60+
61+
errs = append(errs, testErr)
62+
assert.Equal(t, errs, errs.ToError())
63+
}

pkg/errors/status/codes.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const (
3838

3939
// NoPeersFound No peers were discovered/configured
4040
NoPeersFound Code = 6
41+
42+
// MultipleErrors multiple errors occurred
43+
MultipleErrors Code = 7
4144
)
4245

4346
// CodeName maps the codes in this packages to human-readable strings
@@ -49,6 +52,7 @@ var CodeName = map[int32]string{
4952
4: "EMPTY_CERT",
5053
5: "TIMEOUT",
5154
6: "NO_PEERS_FOUND",
55+
7: "MULTIPLE_ERRORS",
5256
}
5357

5458
// ToInt32 cast to int32

pkg/errors/status/status.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/pkg/errors"
1616

17+
"github.com/hyperledger/fabric-sdk-go/pkg/errors/multi"
1718
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
1819
grpcstatus "google.golang.org/grpc/status"
1920
)
@@ -94,8 +95,8 @@ func (g Group) String() string {
9495
return UnknownStatus.String()
9596
}
9697

97-
// FromError returns a Status representing err if it was produced from this
98-
// package, otherwise it returns nil, false.
98+
// FromError returns a Status representing err if available,
99+
// otherwise it returns nil, false.
99100
func FromError(err error) (s *Status, ok bool) {
100101
if err == nil {
101102
return &Status{Code: int32(OK)}, true
@@ -107,6 +108,9 @@ func FromError(err error) (s *Status, ok bool) {
107108
if s, ok := unwrappedErr.(*Status); ok {
108109
return s, true
109110
}
111+
if m, ok := unwrappedErr.(multi.Errors); ok {
112+
return New(ClientStatus, MultipleErrors.ToInt32(), m.Error(), nil), true
113+
}
110114

111115
return nil, false
112116
}

pkg/errors/status/status_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"testing"
1212

13+
"github.com/hyperledger/fabric-sdk-go/pkg/errors/multi"
1314
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
1415
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
1516
"github.com/pkg/errors"
@@ -65,6 +66,14 @@ func TestFromError(t *testing.T) {
6566

6667
s, ok = FromError(fmt.Errorf("Test"))
6768
assert.False(t, ok)
69+
70+
errs := multi.Errors{}
71+
errs = append(errs, fmt.Errorf("Test"))
72+
s, ok = FromError(errs)
73+
assert.True(t, ok)
74+
assert.Equal(t, ClientStatus, s.Group)
75+
assert.EqualValues(t, MultipleErrors.ToInt32(), s.Code)
76+
assert.Equal(t, errs.Error(), s.Message)
6877
}
6978

7079
func TestStatusToError(t *testing.T) {

pkg/fabric-client/channel/channel.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ func (c *Channel) QueryByChaincode(request fab.ChaincodeInvokeRequest) ([][]byte
431431
return nil, err
432432
}
433433
resps, err := queryChaincode(c.clientContext, c.name, request, targets)
434-
return filterProposalResponses(resps, err)
434+
return collectProposalResponses(resps), err
435435
}
436436

437437
// QueryBySystemChaincode invokes a chaincode that isn't part of a channel.
@@ -443,5 +443,5 @@ func (c *Channel) QueryBySystemChaincode(request fab.ChaincodeInvokeRequest) ([]
443443
return nil, err
444444
}
445445
resps, err := queryChaincode(c.clientContext, systemChannel, request, targets)
446-
return filterProposalResponses(resps, err)
446+
return collectProposalResponses(resps), err
447447
}

0 commit comments

Comments
 (0)