Skip to content

Commit

Permalink
Merge pull request #409 from pfleeter/fix-data-conflict-with-min-patc…
Browse files Browse the repository at this point in the history
…h-sync-count

Improve DataConflictException handling in case of partial local modification
  • Loading branch information
Steve Roberts authored Aug 15, 2016
2 parents c660464 + fbf28ef commit b6d4162
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
10 changes: 5 additions & 5 deletions sdk/src/Services/CognitoSync/Custom/SyncManager/Dataset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,13 +566,13 @@ private async Task RunSyncOperationAsync(int retry, CancellationToken cancellati

// push changes to remote
List<Record> localChanges = this.ModifiedRecords;
long maxPatchSyncCount = 0;
long minPatchSyncCount = lastSyncCount;
foreach (Record r in localChanges)
{
//track the max sync count
if (r.SyncCount > maxPatchSyncCount)
if (r.SyncCount < minPatchSyncCount)
{
maxPatchSyncCount = r.SyncCount;
minPatchSyncCount = r.SyncCount;
}
}
if (localChanges.Count != 0)
Expand Down Expand Up @@ -631,9 +631,9 @@ private async Task RunSyncOperationAsync(int retry, CancellationToken cancellati
else
{
//it's possible there is a local dirty record with a stale sync count this will fix it
if (lastSyncCount > maxPatchSyncCount)
if (lastSyncCount > minPatchSyncCount)
{
Local.UpdateLastSyncCount(IdentityId, DatasetName, maxPatchSyncCount);
Local.UpdateLastSyncCount(IdentityId, DatasetName, minPatchSyncCount);
}
#if BCL35
RunSyncOperation(--retry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,8 @@ public void ConditionallyPutRecords(String identityId, String datasetName, List<
* Grab an instance of the record from the local store with the remote change's
* key and the snapshot version.
* 1) If both are null the remote change is new and we should save.
* 2) If both exist but the values and sync counts have changed,
* it has changed locally and we shouldn't overwrite with the remote changes,
* which will still exist in remote.
* 2) If both exist but the value has changed locally we shouldn't overwrite with the remote changes,
* which will still exist in remote, but should update the sync count to avoid a false-conflict later.
* 3) If both exist and the values have not changed, we should save the remote change.
* 4) If the current check exists but it wasn't in the snapshot, we should save.
*/
Expand All @@ -530,15 +529,53 @@ public void ConditionallyPutRecords(String identityId, String datasetName, List<
foreach (Record record in records)
{
Record databaseRecord = this.GetRecord(identityId, datasetName, record.Key);
Record oldDatabaseRecord = localRecordMap.ContainsKey(record.Key) ? localRecordMap[record.Key] : null;
if (databaseRecord != null && oldDatabaseRecord != null
&& (!StringUtils.Equals(databaseRecord.Value, oldDatabaseRecord.Value)
|| databaseRecord.SyncCount != oldDatabaseRecord.SyncCount
|| !StringUtils.Equals(databaseRecord.LastModifiedBy, oldDatabaseRecord.LastModifiedBy)))
{
continue;
Record oldDatabaseRecord = localRecordMap.ContainsKey(record.Key) ? localRecordMap[record.Key] : null;

if (databaseRecord != null && oldDatabaseRecord != null)
{
// The record exists both before and after the update locally, but has it changed?

if (databaseRecord.SyncCount != oldDatabaseRecord.SyncCount
|| !StringUtils.Equals(databaseRecord.LastModifiedBy, oldDatabaseRecord.LastModifiedBy))
{
continue;
}

if (!StringUtils.Equals(databaseRecord.Value, oldDatabaseRecord.Value))
{
if (StringUtils.Equals(record.Value, oldDatabaseRecord.Value))
{
// The value has changed, so this is a local change during the push record operation.
// Avoid a future conflict by updating the metadata so that it looks like the modifications that
// occurred during the put record operation happened after the put operation completed.
Record resolvedRecord =
new Record(
record.Key,
databaseRecord.Value,
record.SyncCount,
record.LastModifiedDate,
record.LastModifiedBy,
databaseRecord.DeviceLastModifiedDate,
true
);

UpdateOrInsertRecord(identityId, datasetName, resolvedRecord);
}
else
{
continue;
}

}
else
{
UpdateOrInsertRecord(identityId, datasetName, record);
}
}
else
{
UpdateOrInsertRecord(identityId, datasetName, record);
}
UpdateOrInsertRecord(identityId, datasetName, record);
}
}

Expand Down

0 comments on commit b6d4162

Please sign in to comment.