Hi @priya.rajagopal, thanks for the quick reply.
Thanks for clarifying the pruning algorithm.,
However, for our case, we’d like a way to minimize the size of the sync until pruning/compaction takes place.
Using the provided CBL Conflict resolution test project, we came up with a few test scenarios:
Method 1 (Leaving entire documents in the bodymap):
func resolveConflicts(revisions revs: [CBLRevision], withProps desiredProps: [String: Any]?, andImage desiredImage: CBLAttachment?) {
database.inTransaction {
var i = 0
for rev in revs as! [CBLSavedRevision] {
let newRev = rev.createRevision() // Create new revision
if (i == 0) { // That's the current / winning revision
newRev.userProperties = desiredProps // Set properties to desired properties
if rev.attachmentNamed("image") != desiredImage {
newRev.setAttachmentNamed("image", withContentType: "image/jpg", content: desiredImage?.content)
}
} else {
// That's a conflicting revision, delete it
newRev.isDeletion = true
}
do {
try newRev.saveAllowingConflict() // Persist the new revisions
} catch let error as NSError {
NSLog("Cannot resolve conflicts with error: %@", error)
return false
}
i += 1
}
return true
}
}
And a document with resolved conflicts looks like this:
[details=doc1]> {
“_sync”:{
“rev”:“3-46bb09aa101b84e555c0b7aee743a5b6”,
“new_rev”:“3-4b8183fb6da995ba83ffed7c46fdbd1e”,
“flags”:20,
“sequence”:158,
“recent_sequences”:[
148,
149,
150,
151,
152,
153,
154,
155,
156,
157,
158
],
“history”:{
“revs”:[
“2-01558dcee47d4d04e617f4d1af0e92b8”,
“3-3532482a66de5f3dcbeeb6cab4496d1e”,
“3-4b8183fb6da995ba83ffed7c46fdbd1e”,
“1-d2e116c4a32ba7a1c6f5d4e81a920368”,
“3-2f26db7ea4ea9fbb3da3ea934584f147”,
“2-a3881738195c82f2e7cd650dcd4eb73a”,
“2-04e44928a189119a4c62eeee1daa8376”,
“2-70eebc24ba94129afa2ac1577fe33401”,
“3-46bb09aa101b84e555c0b7aee743a5b6”,
“2-fed5f0c3f516e077a2d545a96c03bf16”,
“3-fe88f6a6c64407eb404e5f0eb97ecc92”
],
“parents”:[
3,
6,
0,
-1,
7,
3,
3,
3,
9,
3,
5
],
“deleted”:[
1,
2,
4,
10
],
“bodymap”:{
“1”:"{"_deleted":true,“name”:“A Fun Game”,“owner”:“todo”,“type”:“task-list”}",
“10”:"{"_deleted":true,“name”:“Table Soccer”,“owner”:“todo”,“type”:“task-list”}",
“2”:"{"_deleted":true,“name”:“Foosball”,“owner”:“todo”,“type”:“task-list”}",
“4”:"{"_deleted":true,“name”:“Fuzboll”,“owner”:“todo”,“type”:“task-list”}"
},
“channels”:[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
},
“time_saved”:“2017-07-11T14:08:48.291480628-05:00”
},
“name”:“Table Football”,
“owner”:“todo”,
“type”:“task-list”
}[/details]
As you can see, complete documents are stored in the body map.
After some work, found a way to only store > {"_deleted":true}
In the body map–per resolved document
Here’s our method:
Method 2 (complete documents are not stored in the bodymap):
func resolveConflicts(revisions revs: [CBLRevision], withProps desiredProps: [String: Any]?, andImage desiredImage: CBLAttachment?) {
database.inTransaction {
for rev in revs as! [CBLSavedRevision] {
print(rev.properties)
if (rev.properties?["name"]! as? String == "Foosball") { // That's the current / winning revision
let newRev = rev.createRevision() // Create new revision
if rev.attachmentNamed("image") != desiredImage {
newRev.setAttachmentNamed("image", withContentType: "image/jpg", content: desiredImage?.content)
}
do {
try newRev.saveAllowingConflict() // Persist the new revisions
} catch let error as NSError {
NSLog("Cannot resolve conflicts with error: %@", error)
return false
}
} else { // That's a conflicting revision, delete it
do{
try rev.deleteDocument()
} catch let error as NSError{
NSLog("Cannot resolve conflicts with error: %@", error)
return false
}
}
}
return true
}
}
And the document looks like this:
[details=doc2]> {
“_sync”:{
“rev”:“3-a5b50c242841a8f94ee9e867f44aac57”,
“flags”:16,
“sequence”:146,
“recent_sequences”:[
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146
],
“history”:{
“revs”:[
“3-a5b50c242841a8f94ee9e867f44aac57”,
“3-05fd6280bb2b5e667655d9046ce55970”,
“1-d2e116c4a32ba7a1c6f5d4e81a920368”,
“2-a3881738195c82f2e7cd650dcd4eb73a”,
“3-26138aad7f1aeb7c095612cb5bb53b18”,
“2-70eebc24ba94129afa2ac1577fe33401”,
“2-01558dcee47d4d04e617f4d1af0e92b8”,
“3-1470621fa2bb08e2908e7f161b6e71cd”,
“2-fed5f0c3f516e077a2d545a96c03bf16”,
“3-efbe53deec36eef18a532054bdaabccf”,
“2-04e44928a189119a4c62eeee1daa8376”
],
“parents”:[
6,
8,
-1,
2,
5,
2,
2,
3,
2,
10,
2
],
“deleted”:[
1,
4,
7,
9
],
“bodymap”:{
“1”:"{"_deleted":true}",
“4”:"{"_deleted":true}",
“7”:"{"_deleted":true}",
“9”:"{"_deleted":true}"
},
“channels”:[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
},
“time_saved”:“2017-07-11T13:58:53.553483182-05:00”
},
“name”:“Foosball”,
“owner”:“todo”,
“type”:“task-list”
}[/details]
Note, the body map only contains “…”:"{"_deleted":true}" elements
The second method seems like it may work for our use. However, I’m concerned with using rev.deleteDocument() instead of simply setting isDeletion to true. Also, in our second method of conflict resolution, we only use createRevision() on the winning conflict.
What is the expected behavior, and should we be concerned that we are only storing “:”{"_deleted":true} in the elements of the bodymap? I’m not quite sure why, after resolving conflicts, we would need access to entire documents in the bodymap.
Thanks Again,
Caroline