-
-
Save n1schal/0c45802c7e9fc84f987c1d9c6851f07e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Started along with sync initiation | |
public void StartConflictLiveQuery() | |
{ | |
ConflictsLiveQuery = Database.CreateAllDocumentsQuery().ToLiveQuery(); | |
ConflictsLiveQuery.AllDocsMode = AllDocsMode.OnlyConflicts; | |
ConflictsLiveQuery.Changed += HandleConflicts; | |
ConflictsLiveQuery.Start(); | |
} | |
private void HandleConflicts(object sender, QueryChangeEventArgs e) | |
{ | |
var rows = ConflictsLiveQuery?.Rows; | |
if (rows == null) | |
{ | |
return; | |
} | |
foreach (var row in rows) | |
{ | |
var conflicts = row.GetConflictingRevisions().ToArray(); | |
if (conflicts.Length > 1) | |
{ | |
var defaultWinning = conflicts[0]; | |
var type = defaultWinning.GetProperty("type") as string ?? ""; | |
var id = defaultWinning.GetProperty("_id") as string ?? ""; | |
AppLog.WriteLogD(TAG + "ResolveConflicts", "Id: " + id); | |
AppLog.WriteLogD(TAG + "ResolveConflicts", "Document Type: " + type); | |
AppLog.WriteLogD(TAG + "ResolveConflicts", "ConflictsCount: " + conflicts.Length); | |
switch (type) | |
{ | |
// Automatic conflict resolution | |
case "patient": | |
var props = defaultWinning.UserProperties; | |
ResolveConflicts(conflicts, props); | |
break; | |
// N-way merge conflict resolution | |
case "user_info": | |
var merged = NWayMergeConflicts(conflicts); | |
ResolveConflicts(conflicts, merged); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
} | |
private void ResolveConflicts(SavedRevision[] revs, IDictionary<string, object> props) | |
{ | |
Database.RunInTransaction(() => | |
{ | |
var i = 0; | |
foreach (var rev in revs) | |
{ | |
var newRev = rev.CreateRevision(); | |
if (i == 0) | |
{ // Default winning revision | |
newRev.SetUserProperties(props); | |
} | |
else | |
{ | |
newRev.IsDeletion = true; | |
} | |
try | |
{ | |
newRev.Save(true); | |
} | |
catch (Exception e) | |
{ | |
AppLog.WriteLogD(TAG, $"Cannot resolve conflicts with error: {e}"); | |
return false; | |
} | |
i += 1; | |
} | |
return true; | |
}); | |
} | |
private IDictionary<string, object> NWayMergeConflicts(SavedRevision[] revs) | |
{ | |
var parent = FindCommonParent(revs); | |
if (parent == null) | |
{ | |
var defaultWinning = revs[0]; | |
var props = defaultWinning.UserProperties; | |
return props; | |
} | |
var mergedProps = parent.UserProperties ?? new Dictionary<string, object>(); | |
var gotDevToken = false; | |
var gotSubCancelDate = false; | |
var gotPlanId = false; | |
var gotSubName = false; | |
var gotCancelled = false; | |
var gotHasCard = false; | |
var gotSubscribed = false; | |
var gotSubCreateDate = false; | |
var gotExpireDate = false; | |
var gotSubId = false; | |
var gotSubStartDate = false; | |
var gotPhoto = false; | |
var gotPhotoName = false; | |
foreach (var rev in revs) | |
{ | |
var props = rev.UserProperties; | |
if (props != null) | |
{ | |
if (!gotDevToken) | |
{ | |
var devToken = Lookup<string>(props, "device_token"); | |
if (devToken != Lookup<string>(mergedProps, "device_token")) | |
{ | |
mergedProps["device_token"] = devToken; | |
gotDevToken = true; | |
} | |
} | |
if (!gotSubCancelDate) | |
{ | |
var subCancelDate = Lookup<string>(props, "subscription_cancel_date"); | |
if (subCancelDate != Lookup<string>(mergedProps, "subscription_cancel_date")) | |
{ | |
mergedProps["subscription_cancel_date"] = subCancelDate; | |
gotSubCancelDate = true; | |
} | |
} | |
if (!gotPlanId) | |
{ | |
var planId = Lookup<string>(props, "current_planId"); | |
if (planId != Lookup<string>(mergedProps, "current_planId")) | |
{ | |
mergedProps["current_planId"] = planId; | |
gotPlanId = true; | |
} | |
} | |
if (!gotSubName) | |
{ | |
var currentSub = Lookup<string>(props, "current_subscription"); | |
if (currentSub != Lookup<string>(mergedProps, "current_subscription")) | |
{ | |
mergedProps["current_subscription"] = currentSub; | |
gotSubName = true; | |
} | |
} | |
if (!gotCancelled) | |
{ | |
var hasCancelled = LookupNullable<bool>(props, "has_cancelled_subscription"); | |
if (hasCancelled != LookupNullable<bool>(mergedProps, "has_cancelled_subscription")) | |
{ | |
mergedProps["has_cancelled_subscription"] = hasCancelled; | |
gotCancelled = true; | |
} | |
} | |
if (!gotHasCard) | |
{ | |
var hasCard = LookupNullable<bool>(props, "has_card"); | |
if (hasCard != LookupNullable<bool>(mergedProps, "has_card")) | |
{ | |
mergedProps["has_card"] = hasCard; | |
gotHasCard = true; | |
} | |
} | |
if (!gotSubscribed) | |
{ | |
var hasSubscribed = LookupNullable<bool>(props, "subscribed"); | |
if (hasSubscribed != LookupNullable<bool>(mergedProps, "subscribed")) | |
{ | |
mergedProps["subscribed"] = hasSubscribed; | |
gotSubscribed = true; | |
} | |
} | |
if (!gotSubCreateDate) | |
{ | |
var createDate = Lookup<string>(props, "subscription_created_at"); | |
if (createDate != Lookup<string>(mergedProps, "subscription_created_at")) | |
{ | |
mergedProps["subscription_created_at"] = createDate; | |
gotSubCreateDate = true; | |
} | |
} | |
if (!gotExpireDate) | |
{ | |
var expDate = Lookup<string>(props, "subscription_expire_at"); | |
if (expDate != Lookup<string>(mergedProps, "subscription_expire_at")) | |
{ | |
mergedProps["subscription_expire_at"] = expDate; | |
gotExpireDate = true; | |
} | |
} | |
if (!gotSubId) | |
{ | |
var subId = Lookup<string>(props, "subscription_id"); | |
if (subId != Lookup<string>(mergedProps, "subscription_id")) | |
{ | |
mergedProps["subscription_id"] = subId; | |
gotSubId = true; | |
} | |
} | |
if (!gotSubStartDate) | |
{ | |
var subStartDate = Lookup<string>(props, "subscription_start_date"); | |
if (subStartDate != Lookup<string>(mergedProps, "subscription_start_date")) | |
{ | |
mergedProps["subscription_start_date"] = subStartDate; | |
gotSubStartDate = true; | |
} | |
} | |
if (!gotPhoto) | |
{ | |
var photo = Lookup<string>(props, "photo"); | |
if (photo != Lookup<string>(mergedProps, "photo")) | |
{ | |
mergedProps["photo"] = photo; | |
gotPhoto = true; | |
} | |
} | |
if (!gotPhotoName) | |
{ | |
var photoName = Lookup<string>(props, "photo_name"); | |
if (photoName != Lookup<string>(mergedProps, "photo_name")) | |
{ | |
mergedProps["photo_name"] = photoName; | |
gotPhotoName = true; | |
} | |
} | |
if (gotDevToken && gotSubCancelDate && gotPlanId && gotSubName && gotCancelled | |
&& gotHasCard && gotSubscribed && gotSubCreateDate && gotExpireDate && | |
gotSubId && gotSubStartDate && gotPhoto && gotPhotoName) | |
{ | |
break; | |
} | |
} | |
} | |
return mergedProps; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment