Skip to content

Commit 175a5e0

Browse files
author
Chris Elder
committed
[FAB-5973] CouchDB error when document deleted twice
CouchDB will throw an error if a document is deleted in more than one update batch. The first batch actually deletes the document, but if the delete is included in a subsequent batch an exception will be thrown since the document revision will not be resolved correctly. In this case, the batch update should ignore documents that are already deleted. Update documents are not impacted since the update operation can correctly resolve the CouchDB revision info. Change-Id: Ie4a329cd8d0be8578890657cdbabdb508f7cd3d6 Signed-off-by: Chris Elder <chris.elder@us.ibm.com>
1 parent 6b8a4a6 commit 175a5e0

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

core/ledger/kvledger/txmgmt/statedb/statecouchdb/statecouchdb.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ var binaryWrapper = "valueBytes"
3434
// currently defaulted to 0 and is not used
3535
var querySkip = 0
3636

37+
// BatchDocument defines a document for a batch
38+
type BatchableDocument struct {
39+
CouchDoc couchdb.CouchDoc
40+
Deleted bool
41+
}
42+
3743
// VersionedDBProvider implements interface VersionedDBProvider
3844
type VersionedDBProvider struct {
3945
couchInstance *couchdb.CouchInstance
@@ -380,7 +386,7 @@ func (vdb *VersionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version
380386
}
381387

382388
// Add the current docment to the update map
383-
batchUpdateMap[string(compositeKey)] = couchDoc
389+
batchUpdateMap[string(compositeKey)] = BatchableDocument{CouchDoc: *couchDoc, Deleted: isDelete}
384390

385391
}
386392
}
@@ -389,7 +395,8 @@ func (vdb *VersionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version
389395

390396
batchUpdateDocs := []*couchdb.CouchDoc{}
391397
for _, updateDocument := range batchUpdateMap {
392-
batchUpdateDocs = append(batchUpdateDocs, updateDocument.(*couchdb.CouchDoc))
398+
batchUpdateDocument := updateDocument.(BatchableDocument)
399+
batchUpdateDocs = append(batchUpdateDocs, &batchUpdateDocument.CouchDoc)
393400
}
394401

395402
// Do the bulk update into couchdb
@@ -407,18 +414,31 @@ func (vdb *VersionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version
407414
// If the document returned an error, retry the individual document
408415
if respDoc.Ok != true {
409416

410-
// Save the individual document to couchdb
411-
// Note that this will do retries as needed
412-
_, err := vdb.db.SaveDoc(respDoc.ID, "", batchUpdateMap[respDoc.ID].(*couchdb.CouchDoc))
417+
batchUpdateDocument := batchUpdateMap[respDoc.ID].(BatchableDocument)
418+
419+
var err error
413420

414-
// If the single document update with retries returns an error, then throw the error
421+
// Check to see if the document was added to the batch as a delete type document
422+
if batchUpdateDocument.Deleted {
423+
// If this is a deleted document, then retry the delete
424+
// If the delete fails due to a document not being found (404 error),
425+
// the document has already been deleted and the DeleteDoc will not return an error
426+
err = vdb.db.DeleteDoc(respDoc.ID, "")
427+
} else {
428+
// Save the individual document to couchdb
429+
// Note that this will do retries as needed
430+
_, err = vdb.db.SaveDoc(respDoc.ID, "", &batchUpdateDocument.CouchDoc)
431+
}
432+
433+
// If the single document update or delete returns an error, then throw the error
415434
if err != nil {
416435

417436
errorString := fmt.Sprintf("Error occurred while saving document ID = %v Error: %s Reason: %s\n",
418437
respDoc.ID, respDoc.Error, respDoc.Reason)
419438

420439
logger.Errorf(errorString)
421440
return fmt.Errorf(errorString)
441+
422442
}
423443
}
424444
}

0 commit comments

Comments
 (0)