@@ -1016,9 +1016,22 @@ func (db *DatabaseCollectionWithUser) updateHLV(ctx context.Context, d *Document
1016
1016
}
1017
1017
// update the cvCAS on the SGWrite event too
1018
1018
d .HLV .CurrentVersionCAS = expandMacroCASValueUint64
1019
+ case ExistingVersionLegacyRev :
1020
+ revTreeEncodedCV , err := LegacyRevToRevTreeEncodedVersion (d .GetRevTreeID ())
1021
+ if err != nil {
1022
+ return nil , err
1023
+ }
1024
+ err = d .HLV .AddVersion (revTreeEncodedCV )
1025
+ if err != nil {
1026
+ return nil , err
1027
+ }
1028
+ // update the cvCAS on the SGWrite event too
1029
+ d .HLV .CurrentVersionCAS = expandMacroCASValueUint64
1019
1030
case NoHLVUpdateForTest :
1020
1031
// no hlv update event for testing purposes only (used to simulate pre upgraded write)
1021
1032
return d , nil
1033
+ default :
1034
+ return nil , base .RedactErrorf ("Unexpected docUpdateEvent %v in updateHLV for doc %s" , docUpdateEvent , base .UD (d .ID ))
1022
1035
}
1023
1036
d .SyncData .SetCV (d .HLV )
1024
1037
return d , nil
@@ -1449,24 +1462,45 @@ func (db *DatabaseCollectionWithUser) PutExistingCurrentVersion(ctx context.Cont
1449
1462
1450
1463
// Adds an existing revision to a document along with its history (list of rev IDs.)
1451
1464
func (db * DatabaseCollectionWithUser ) PutExistingRev (ctx context.Context , newDoc * Document , docHistory []string , noConflicts bool , forceAllConflicts bool , existingDoc * sgbucket.BucketDocument , docUpdateEvent DocUpdateType ) (doc * Document , newRevID string , err error ) {
1452
- return db .PutExistingRevWithConflictResolution (ctx , newDoc , docHistory , noConflicts , nil , forceAllConflicts , existingDoc , docUpdateEvent )
1465
+ opts := putDocOptions {
1466
+ newDoc : newDoc ,
1467
+ revTreeHistory : docHistory ,
1468
+ noConflicts : noConflicts ,
1469
+ forceAllowConflictingTombstone : forceAllConflicts ,
1470
+ existingDoc : existingDoc ,
1471
+ docUpdateEvent : docUpdateEvent ,
1472
+ }
1473
+ return db .PutExistingRevWithConflictResolution (ctx , opts )
1474
+ }
1475
+
1476
+ // putDocOptions encapsulates the options for putting a document revision.
1477
+ type putDocOptions struct {
1478
+ newDoc * Document // the next contents of the incoming document
1479
+ revTreeHistory []string // list of rev tree IDs. The first entry must be the revtree ID that will be added.
1480
+ docUpdateEvent DocUpdateType // new write, existing write, import etc
1481
+ noConflicts bool // If true, return 409 on any conflict writes
1482
+ forceAllowConflictingTombstone bool // If true, do not flag an incoming tombstone as a conflict if the existing document is a tombstone
1483
+ conflictResolver * ConflictResolver // If provided, will be used to resolve conflicts if noConflicts is false and a conflict is detected
1484
+ existingDoc * sgbucket.BucketDocument // optional, prevents fetching the document from the bucket
1453
1485
}
1454
1486
1455
- // PutExistingRevWithConflictResolution Adds an existing revision to a document along with its history (list of rev IDs.)
1487
+ // PutExistingRevWithConflictResolution adds an existing revision to a document along with its history.
1456
1488
// If this new revision would result in a conflict:
1457
1489
// 1. If noConflicts == false, the revision will be added to the rev tree as a conflict
1458
1490
// 2. If noConflicts == true and a conflictResolverFunc is not provided, a 409 conflict error will be returned
1459
1491
// 3. If noConflicts == true and a conflictResolverFunc is provided, conflicts will be resolved and the result added to the document.
1460
- func (db * DatabaseCollectionWithUser ) PutExistingRevWithConflictResolution (ctx context.Context , newDoc * Document , docHistory [] string , noConflicts bool , conflictResolver * ConflictResolver , forceAllowConflictingTombstone bool , existingDoc * sgbucket. BucketDocument , docUpdateEvent DocUpdateType ) (doc * Document , newRevID string , err error ) {
1461
- newRev := docHistory [0 ]
1492
+ func (db * DatabaseCollectionWithUser ) PutExistingRevWithConflictResolution (ctx context.Context , opts putDocOptions ) (doc * Document , newRevID string , err error ) {
1493
+ newRev := opts . revTreeHistory [0 ]
1462
1494
generation , _ := ParseRevID (ctx , newRev )
1463
1495
if generation < 0 {
1464
1496
return nil , "" , base .HTTPErrorf (http .StatusBadRequest , "Invalid revision ID" )
1465
1497
}
1466
1498
1499
+ newDoc := opts .newDoc
1500
+ docHistory := opts .revTreeHistory
1467
1501
allowImport := db .UseXattrs ()
1468
1502
updateRevCache := true
1469
- doc , _ , err = db .updateAndReturnDoc (ctx , newDoc .ID , allowImport , & newDoc .DocExpiry , nil , docUpdateEvent , existingDoc , false , updateRevCache , func (doc * Document ) (resultDoc * Document , resultAttachmentData updatedAttachments , createNewRevIDSkipped bool , updatedExpiry * uint32 , resultErr error ) {
1503
+ doc , _ , err = db .updateAndReturnDoc (ctx , newDoc .ID , allowImport , & newDoc .DocExpiry , nil , opts . docUpdateEvent , opts . existingDoc , false , updateRevCache , func (doc * Document ) (resultDoc * Document , resultAttachmentData updatedAttachments , createNewRevIDSkipped bool , updatedExpiry * uint32 , resultErr error ) {
1470
1504
// (Be careful: this block can be invoked multiple times if there are races!)
1471
1505
1472
1506
var isSgWrite bool
@@ -1507,13 +1541,13 @@ func (db *DatabaseCollectionWithUser) PutExistingRevWithConflictResolution(ctx c
1507
1541
// Conflict-free mode check
1508
1542
1509
1543
// We only bypass conflict resolution for incoming tombstones if the local doc is also a tombstone
1510
- allowConflictingTombstone := forceAllowConflictingTombstone && doc .IsDeleted ()
1544
+ allowConflictingTombstone := opts . forceAllowConflictingTombstone && doc .IsDeleted ()
1511
1545
1512
- if ! allowConflictingTombstone && db .IsIllegalConflict (ctx , doc , parent , newDoc .Deleted , noConflicts , docHistory ) {
1513
- if conflictResolver == nil {
1546
+ if ! allowConflictingTombstone && db .IsIllegalConflict (ctx , doc , parent , newDoc .Deleted , opts . noConflicts , docHistory ) {
1547
+ if opts . conflictResolver == nil {
1514
1548
return nil , nil , false , nil , base .HTTPErrorf (http .StatusConflict , "Document revision conflict" )
1515
1549
}
1516
- _ , updatedHistory , err := db .resolveConflict (ctx , doc , newDoc , docHistory , conflictResolver )
1550
+ _ , updatedHistory , err := db .resolveConflict (ctx , doc , newDoc , docHistory , opts . conflictResolver )
1517
1551
if err != nil {
1518
1552
base .InfofCtx (ctx , base .KeyCRUD , "Error resolving conflict for %s: %v" , base .UD (doc .ID ), err )
1519
1553
return nil , nil , false , nil , err
0 commit comments