private void SynchronizeInternalAsync(ISyncCallback callback, long syncSequenceId, int retry) { if (retry < 0) { var e = new SyncConflictingException(); if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(e, "Sync failed due to retry less than 0"); } callback.OnError(this, new SyncConflictingException()); return; } // pull from remote var lastSyncRevisions = _local.GetLastSyncRevision(IdentityId, Name); _remote.ListUpdatesAsync(IdentityId, Name, lastSyncRevisions, (listUpdatesErr, datasetUpdates) => { if (syncSequenceId != _currentSyncSequenceId) { var e = new SyncCanceledException(); callback.OnError(this, e); if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(e, "INTERNAL LOG - Sync Failed due to inconsistent syncSequenceId."); } return; } if (listUpdatesErr != null) { var e = new SyncNetworkException("Failed to pull from remote", listUpdatesErr); if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(e, "INTERNAL LOG - Failed to pull from remote"); } callback.OnError(this, e); return; } if (!MergeRemoteRecords(callback, datasetUpdates)) { return; } // push to remote. // includes the records whose region is different. var localChanges = _local.GetDirtyRecords(IdentityId, Name); if (localChanges.Count == 0) { callback.OnSuccess(this); return; } _remote.PutRecordsAsync(IdentityId, Name, SdkUtils.ConvertSyncRevisionToString(datasetUpdates.SyncRevisions), datasetUpdates.SyncSessionToken, localChanges, (putErr, putResult) => { if (syncSequenceId != _currentSyncSequenceId) { var e = new SyncCanceledException(); if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(e, "INTERNAL LOG - Sync failed due to inconsistency of syncSequenceId"); } callback.OnError(this, e); return; } if (putErr != null) { if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(putErr, "INTERNAL LOG - Failed to push to remote: {0}", putErr.Message); } if (ErrorResponseException.IsDatasetConflict(putErr)) { SynchronizeInternalAsync(callback, syncSequenceId, --retry); return; } callback.OnError(this, new SyncNetworkException("Failed to push to remote", putErr)); return; } _local.ConditionallyPutRecords(IdentityId, Name, putResult.Records, localChanges); _local.UpdateLastSyncRevision(IdentityId, Name, putResult.SyncRevisions); callback.OnSuccess(this); }); }); }