Skip to content

CBG-4782: new rev tree property for ISGR replications #7671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions db/active_replicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ func connect(arc *activeReplicatorCommon, idSuffix string) (blipSender *blip.Sen
return nil, nil, err
}

// set client type to SGW on active peer
bsc.SetClientType(BLIPClientTypeSGR2)

// set active subprotocol after handshake
err = bsc.SetActiveCBMobileSubprotocol(blipContext.ActiveSubprotocol())
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion db/blip.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func defaultBlipLogger(ctx context.Context) blip.LogFn {
}

// blipRevMessageProperties returns a set of BLIP message properties for the given parameters.
func blipRevMessageProperties(revisionHistory []string, deleted bool, seq SequenceID, replacedRevID string) blip.Properties {
func blipRevMessageProperties(revisionHistory []string, deleted bool, seq SequenceID, replacedRevID string, revTreeProperty []string) blip.Properties {
properties := make(blip.Properties)

// TODO: Assert? db.SequenceID.MarshalJSON can never error
Expand All @@ -95,6 +95,10 @@ func blipRevMessageProperties(revisionHistory []string, deleted bool, seq Sequen
properties[RevMessageHistory] = strings.Join(revisionHistory, ",")
}

if len(revTreeProperty) > 0 {
properties[RevMessageTreeHistory] = strings.Join(revTreeProperty, ",")
}

if deleted {
properties[RevMessageDeleted] = "1"
}
Expand Down
19 changes: 18 additions & 1 deletion db/blip_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -908,12 +908,18 @@

if redactedRev != nil {
var history []string
var revTreeProperty []string
if !bsc.useHLV() {
history = toHistory(redactedRev.History, knownRevs, maxHistory)
} else {
history = append(history, redactedRev.hlvHistory)
}
properties := blipRevMessageProperties(history, redactedRev.Deleted, seq, "")
if bsc.sendRevTreeProperty() {
revTreeProperty = append(revTreeProperty, redactedRev.RevID)
revTreeProperty = append(revTreeProperty, toHistory(redactedRev.History, knownRevs, maxHistory)...)
}

properties := blipRevMessageProperties(history, redactedRev.Deleted, seq, "", revTreeProperty)
return bsc.sendRevisionWithProperties(ctx, sender, docID, revID, collectionIdx, redactedRev.BodyBytes, nil, properties, seq, nil)
}

Expand Down Expand Up @@ -1078,6 +1084,9 @@
var incomingHLV *HybridLogicalVector
// Build history/HLV
var legacyRevList []string
// we can probably use legacyRevList instead of this but to avoid hooking this up to write code we will use
Copy link
Preview

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This TODO comment explains implementation details rather than intent. Consider replacing with a comment that explains why a separate list is needed for the rev tree property, or reference the specific ticket (CBG-4790) that will address this.

Copilot uses AI. Check for mistakes.

// separate list for now, pending CBG-4790
var revTreeProperty []string
changeIsVector := strings.Contains(rev, "@")
if !bh.useHLV() || !changeIsVector {
newDoc.RevID = rev
Expand All @@ -1103,6 +1112,14 @@
newDoc.HLV = incomingHLV
}

// if the client is SGW and there are no legacy revs being sent (i.e. doc is no pre upgraded doc) check the rev tree property
if bh.clientType == BLIPClientTypeSGR2 && len(legacyRevList) == 0 {
revTree, ok := rq.Properties[RevMessageTreeHistory]
if ok {
revTreeProperty = append(revTreeProperty, strings.Split(revTree, ",")...)

Check failure on line 1119 in db/blip_handler.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to revTreeProperty (ineffassign)

Check failure on line 1119 in db/blip_handler.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to revTreeProperty (ineffassign)
}
}

newDoc.UpdateBodyBytes(bodyBytes)

injectedAttachmentsForDelta := false
Expand Down
22 changes: 20 additions & 2 deletions db/blip_sync_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,17 @@
func (bsc *BlipSyncContext) sendDelta(ctx context.Context, sender *blip.Sender, docID string, collectionIdx *int, deltaSrcRevID string, revDelta *RevisionDelta, seq SequenceID, resendFullRevisionFunc func() error) error {

var history []string
var revTreeProperty []string
if bsc.useHLV() {
history = append(history, revDelta.HlvHistory)
} else {
history = revDelta.RevisionHistory
}
properties := blipRevMessageProperties(history, revDelta.ToDeleted, seq, "")
if bsc.sendRevTreeProperty() {
revTreeProperty = append(revTreeProperty, revDelta.ToRevID)
revTreeProperty = append(revTreeProperty, revDelta.RevisionHistory...)
}
properties := blipRevMessageProperties(history, revDelta.ToDeleted, seq, "", revTreeProperty)
properties[RevMessageDeltaSrc] = deltaSrcRevID

base.DebugfCtx(ctx, base.KeySync, "Sending rev %q %s as delta. DeltaSrc:%s", base.UD(docID), revDelta.ToRevID, deltaSrcRevID)
Expand Down Expand Up @@ -768,14 +773,20 @@
history = append(history, docRev.hlvHistory)
}
}

var revTreeHistoryProperty []string
if legacyRev {
// append current revID and rest of rev tree after hlv history
revTreeHistory := toHistory(docRev.History, knownRevs, maxHistory)
history = append(history, docRev.RevID)
history = append(history, revTreeHistory...)
} else if bsc.sendRevTreeProperty() {
// if no legacy revs being sent and we are communicating with SGW client we should send revision history in the rev message
revTreeHistoryProperty = append(revTreeHistoryProperty, docRev.RevID) // we need current rev
revTreeHistoryProperty = append(revTreeHistoryProperty, toHistory(docRev.History, knownRevs, maxHistory)...)
}

properties := blipRevMessageProperties(history, docRev.Deleted, seq, replacedRevID)
properties := blipRevMessageProperties(history, docRev.Deleted, seq, replacedRevID, revTreeHistoryProperty)
if base.LogDebugEnabled(ctx, base.KeySync) {
replacedRevMsg := ""
if replacedRevID != "" {
Expand Down Expand Up @@ -851,3 +862,10 @@
func (bsc *BlipSyncContext) useHLV() bool {
return bsc.activeCBMobileSubprotocol >= CBMobileReplicationV4
}

// sendRevTreeProperty returns true if the rev tree property should be sent in the rev message. That is if we are
// replicating with version vectors and the client we're communicating with is a SGW peer
func (bsc *BlipSyncContext) sendRevTreeProperty() bool {
return bsc.activeCBMobileSubprotocol >= CBMobileReplicationV4 && bsc.clientType == BLIPClientTypeSGR2
}

Check failure on line 871 in db/blip_sync_context.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (goimports)

Check failure on line 871 in db/blip_sync_context.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (goimports)
1 change: 1 addition & 0 deletions db/blip_sync_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const (
RevMessageDeleted = "deleted"
RevMessageSequence = "sequence"
RevMessageHistory = "history"
RevMessageTreeHistory = "revTree"
RevMessageNoConflicts = "noconflicts"
RevMessageDeltaSrc = "deltaSrc"
RevMessageReplacedRev = "replacedRev"
Expand Down
Loading