Skip to content

Commit

Permalink
[FAB-9121] Retry on premature execution error
Browse files Browse the repository at this point in the history
Parse the error 'premature execution' and add
it to the the default set of transient errors.

Change-Id: I823003bf8d038d0883fe59dbe54f977d14023e82
Signed-off-by: Bob Stasyszyn <Bob.Stasyszyn@securekey.com>
  • Loading branch information
bstasyszyn committed Mar 26, 2018
1 parent 46c6fbb commit 84bff1a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
2 changes: 2 additions & 0 deletions pkg/common/errors/retry/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var DefaultOpts = Opts{
var DefaultRetryableCodes = map[status.Group][]status.Code{
status.EndorserClientStatus: []status.Code{
status.EndorsementMismatch,
status.PrematureChaincodeExecution,
},
status.EndorserServerStatus: []status.Code{
status.Code(common.Status_SERVICE_UNAVAILABLE),
Expand Down Expand Up @@ -67,6 +68,7 @@ var DefaultRetryableCodes = map[status.Group][]status.Code{
var ChannelClientRetryableCodes = map[status.Group][]status.Code{
status.EndorserClientStatus: []status.Code{
status.ConnectionFailed, status.EndorsementMismatch,
status.PrematureChaincodeExecution,
},
status.EndorserServerStatus: []status.Code{
status.Code(common.Status_SERVICE_UNAVAILABLE),
Expand Down
5 changes: 5 additions & 0 deletions pkg/common/errors/status/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ const (

// NoMatchingOrdererEntity is if entityMatchers are unable to find any matchingOrderer
NoMatchingOrdererEntity Code = 23

// PrematureChaincodeExecution indicates that an attempt was made to invoke a chaincode that's
// in the process of being launched.
PrematureChaincodeExecution Code = 24
)

// CodeName maps the codes in this packages to human-readable strings
Expand All @@ -77,6 +81,7 @@ var CodeName = map[int32]string{
21: "NO_MATCHING_CERTIFICATE_AUTHORITY_ENTITY",
22: "NO_MATCHING_PEER_ENTITY",
23: "NO_MATCHING_ORDERER_ENTITY",
24: "PREMATURE_CHAINCODE_EXECUTION",
}

// ToInt32 cast to int32
Expand Down
18 changes: 17 additions & 1 deletion pkg/fab/peer/peerendorser.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ func (p *peerEndorser) sendProposal(ctx reqContext.Context, proposal fab.Process
if ok {
code, message, extractErr := extractChaincodeError(rpcStatus)
if extractErr != nil {
err = status.NewFromGRPCStatus(rpcStatus)
code, message, extractErr := extractPrematureExecutionError(rpcStatus)
if extractErr != nil {
err = status.NewFromGRPCStatus(rpcStatus)
} else {
err = status.New(status.EndorserClientStatus, code, message, nil)
}
} else {
err = status.NewFromExtractedChaincodeError(code, message)
}
Expand Down Expand Up @@ -198,6 +203,17 @@ func extractChaincodeError(status *grpcstatus.Status) (int, string, error) {
return code, message, errors.Errorf("Unable to parse GRPC Status Message Code: %v Message: %v", code, message)
}

func extractPrematureExecutionError(grpcstat *grpcstatus.Status) (int32, string, error) {
if grpcstat.Code().String() != "Unknown" || grpcstat.Message() == "" {
return 0, "", errors.New("not a premature execution error")
}
index := strings.Index(grpcstat.Message(), "premature execution")
if index == -1 {
return 0, "", errors.New("not a premature execution error")
}
return int32(status.PrematureChaincodeExecution), grpcstat.Message()[index:], nil
}

// getChaincodeResponseStatus gets the actual response status from response.Payload.extension.Response.status, as fabric always returns actual 200
func getChaincodeResponseStatus(response *pb.ProposalResponse) int32 {
if response.Payload != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/fab/peer/peerendorser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,19 @@ func TestExtractChainCodeError(t *testing.T) {
t.Fatalf("Expected message not found")
}
}

func TestExtractPrematureExecError(t *testing.T) {
err := grpcstatus.New(grpcCodes.Unknown, "some error")
_, _, e := extractPrematureExecutionError(err)
assert.EqualError(t, e, "not a premature execution error")

err = grpcstatus.New(grpcCodes.Unknown, "transaction returned with failure: premature execution - chaincode (somecc:v1) is being launched")
code, message, _ := extractPrematureExecutionError(err)
assert.EqualValues(t, int32(status.PrematureChaincodeExecution), code, "Expected premature execution error")
assert.EqualValues(t, "premature execution - chaincode (somecc:v1) is being launched", message, "Invalid message")

err = grpcstatus.New(grpcCodes.Unknown, "transaction returned with failure: premature execution - chaincode (somecc:v1) launched and waiting for registration")
code, message, _ = extractPrematureExecutionError(err)
assert.EqualValues(t, int32(status.PrematureChaincodeExecution), code, "Expected premature execution error")
assert.EqualValues(t, "premature execution - chaincode (somecc:v1) launched and waiting for registration", message, "Invalid message")
}

0 comments on commit 84bff1a

Please sign in to comment.