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

Commit 9093022

Browse files
committed
[FAB-9935] retry on 'chaincode is already launching'
- this error is removed in fabric v1.2, but we are still handling it for v1.1 Change-Id: I4a4f5b8b18eaabc6007a5e4dca3f4b1a0f84afef Signed-off-by: Sudesh Shetty <sudesh.shetty@securekey.com>
1 parent 914555e commit 9093022

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

pkg/common/errors/retry/defaults.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ var DefaultRetryableCodes = map[status.Group][]status.Code{
7171
status.EndorserClientStatus: {
7272
status.EndorsementMismatch,
7373
status.PrematureChaincodeExecution,
74+
status.ChaincodeAlreadyLaunching,
7475
},
7576
status.EndorserServerStatus: {
7677
status.Code(common.Status_SERVICE_UNAVAILABLE),
@@ -99,6 +100,7 @@ var ResMgmtDefaultRetryableCodes = map[status.Group][]status.Code{
99100
status.EndorserClientStatus: {
100101
status.EndorsementMismatch,
101102
status.PrematureChaincodeExecution,
103+
status.ChaincodeAlreadyLaunching,
102104
},
103105
status.EndorserServerStatus: {
104106
status.Code(common.Status_SERVICE_UNAVAILABLE),
@@ -129,6 +131,7 @@ var ChannelClientRetryableCodes = map[status.Group][]status.Code{
129131
status.EndorserClientStatus: {
130132
status.ConnectionFailed, status.EndorsementMismatch,
131133
status.PrematureChaincodeExecution,
134+
status.ChaincodeAlreadyLaunching,
132135
},
133136
status.EndorserServerStatus: {
134137
status.Code(common.Status_SERVICE_UNAVAILABLE),

pkg/common/errors/status/codes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ const (
6363

6464
// NoMatchingChannelEntity is if entityMatchers are unable to find any matchingChannel
6565
NoMatchingChannelEntity Code = 25
66+
67+
// ChaincodeAlreadyLaunching indicates that an attempt for multiple simultaneous invokes was made to launch chaincode
68+
ChaincodeAlreadyLaunching Code = 26
6669
)
6770

6871
// CodeName maps the codes in this packages to human-readable strings

pkg/fab/peer/peerendorser.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const (
3535
// GRPC max message size (same as Fabric)
3636
maxCallRecvMsgSize = 100 * 1024 * 1024
3737
maxCallSendMsgSize = 100 * 1024 * 1024
38+
statusCodeUnknown = "Unknown"
3839
)
3940

4041
// peerEndorser enables access to a GRPC-based endorser for running transaction proposal simulations
@@ -158,12 +159,20 @@ func (p *peerEndorser) sendProposal(ctx reqContext.Context, proposal fab.Process
158159
if ok {
159160
code, message, extractErr := extractChaincodeError(rpcStatus)
160161
if extractErr != nil {
162+
161163
code, message1, extractErr := extractPrematureExecutionError(rpcStatus)
164+
165+
if extractErr != nil {
166+
//if not premation excution error, then look for chaincode already launching error
167+
code, message1, extractErr = extractChaincodeAlreadyLaunchingError(rpcStatus)
168+
}
169+
162170
if extractErr != nil {
163171
err = status.NewFromGRPCStatus(rpcStatus)
164172
} else {
165173
err = status.New(status.EndorserClientStatus, code, message1, nil)
166174
}
175+
167176
} else {
168177
err = status.NewFromExtractedChaincodeError(code, message)
169178
}
@@ -179,7 +188,7 @@ func (p *peerEndorser) sendProposal(ctx reqContext.Context, proposal fab.Process
179188
func extractChaincodeError(status *grpcstatus.Status) (int, string, error) {
180189
var code int
181190
var message string
182-
if status.Code().String() != "Unknown" || status.Message() == "" {
191+
if status.Code().String() != statusCodeUnknown || status.Message() == "" {
183192
return 0, "", errors.New("Unable to parse GRPC status message")
184193
}
185194
statusLength := len("status:")
@@ -227,7 +236,7 @@ func checkMessage(status *grpcstatus.Status, messageLength int, message string)
227236
}
228237

229238
func extractPrematureExecutionError(grpcstat *grpcstatus.Status) (int32, string, error) {
230-
if grpcstat.Code().String() != "Unknown" || grpcstat.Message() == "" {
239+
if grpcstat.Code().String() != statusCodeUnknown || grpcstat.Message() == "" {
231240
return 0, "", errors.New("not a premature execution error")
232241
}
233242
index := strings.Index(grpcstat.Message(), "premature execution")
@@ -237,6 +246,17 @@ func extractPrematureExecutionError(grpcstat *grpcstatus.Status) (int32, string,
237246
return int32(status.PrematureChaincodeExecution), grpcstat.Message()[index:], nil
238247
}
239248

249+
func extractChaincodeAlreadyLaunchingError(grpcstat *grpcstatus.Status) (int32, string, error) {
250+
if grpcstat.Code().String() != statusCodeUnknown || grpcstat.Message() == "" {
251+
return 0, "", errors.New("not a chaincode already launching error")
252+
}
253+
index := strings.Index(grpcstat.Message(), "error chaincode is already launching:")
254+
if index == -1 {
255+
return 0, "", errors.New("not a chaincode already launching error")
256+
}
257+
return int32(status.ChaincodeAlreadyLaunching), grpcstat.Message()[index:], nil
258+
}
259+
240260
// getChaincodeResponseStatus gets the actual response status from response.Payload.extension.Response.status, as fabric always returns actual 200
241261
func getChaincodeResponseStatus(response *pb.ProposalResponse) int32 {
242262
if response.Payload != nil {

pkg/fab/peer/peerendorser_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ func TestExtractChainCodeError(t *testing.T) {
298298
}
299299

300300
func TestExtractPrematureExecError(t *testing.T) {
301+
301302
err := grpcstatus.New(grpcCodes.Unknown, "some error")
302303
_, _, e := extractPrematureExecutionError(err)
303304
assert.EqualError(t, e, "not a premature execution error")
@@ -313,6 +314,26 @@ func TestExtractPrematureExecError(t *testing.T) {
313314
assert.EqualValues(t, "premature execution - chaincode (somecc:v1) launched and waiting for registration", message, "Invalid message")
314315
}
315316

317+
func TestExtractChaincodeAlreadyLaunchingError(t *testing.T) {
318+
319+
err := grpcstatus.New(grpcCodes.Unknown, "some error")
320+
_, _, e := extractPrematureExecutionError(err)
321+
assert.EqualError(t, e, "not a premature execution error")
322+
323+
err = grpcstatus.New(grpcCodes.Unknown, "error executing chaincode: error chaincode is already launching: somecc:v1")
324+
code, message, extractErr := extractChaincodeAlreadyLaunchingError(err)
325+
assert.EqualValues(t, int32(status.ChaincodeAlreadyLaunching), code, "Expected chaincode already launching error")
326+
assert.EqualValues(t, "error chaincode is already launching: somecc:v1", message, "Invalid message")
327+
assert.Nil(t, extractErr)
328+
329+
err = grpcstatus.New(grpcCodes.Unknown, "error executing chaincode: some random error: somecc:v1")
330+
code, message, extractErr = extractChaincodeAlreadyLaunchingError(err)
331+
assert.NotNil(t, extractErr)
332+
assert.EqualValues(t, 0, code)
333+
assert.Empty(t, message)
334+
335+
}
336+
316337
func TestChaincodeStatusFromResponse(t *testing.T) {
317338
//For error response
318339
response := &pb.ProposalResponse{

0 commit comments

Comments
 (0)