private void StartSynchronizeInternalAsync(ISyncCallback callback) { if (SdkUtils.UnknownIdentityId == _identityId || this._isAnonymousUser) { _logger.DebugFormat("Sync is cancelled since the user has not full login."); callback.OnError(this, new SyncCanceledException("Sync is cancelled since user has not login yet.")); return; } _currentSyncSequenceId++; SynchronizeInternalAsync(callback, _currentSyncSequenceId, MaxRetry); }
public void SynchronizeOnWifiOnlyAsync(ISyncCallback callback) { if (callback == null) { throw new ArgumentNullException("callback"); } CancelPendingCallbacks(); if (Application.internetReachability != NetworkReachability.ReachableViaLocalAreaNetwork) { _lastPendingCallbackWifiOnly = callback; return; } StartSynchronizeInternalAsync(callback); }
public void SynchronizeOnConnectivityAsync(ISyncCallback callback) { if (callback == null) { throw new ArgumentNullException("callback"); } CancelPendingCallbacks(); if (Application.internetReachability == NetworkReachability.NotReachable) { _lastPendingCallback = callback; return; } StartSynchronizeInternalAsync(callback); }
public void SynchronizeAsync(ISyncCallback callback) { if (callback == null) { throw new ArgumentNullException("callback"); } CancelPendingCallbacks(); if (Application.internetReachability == NetworkReachability.NotReachable) { callback.OnError(this, new SyncCanceledException()); return; } StartSynchronizeInternalAsync(callback); }
private void CancelPendingCallbacks() { var localPendingCallback = _lastPendingCallback; if (localPendingCallback != null) { _lastPendingCallback = null; localPendingCallback.OnError(this, new SyncCanceledException()); } var localPendingCallbackWifiOnly = _lastPendingCallbackWifiOnly; if (localPendingCallbackWifiOnly != null) { _lastPendingCallbackWifiOnly = null; localPendingCallbackWifiOnly.OnError(this, new SyncCanceledException()); } }
private void OnNetworkReachabilityChanged(NetworkReachability networkreachability) { var localPendingCallBack = _lastPendingCallback; if (localPendingCallBack != null && networkreachability != NetworkReachability.NotReachable) { _lastPendingCallback = null; StartSynchronizeInternalAsync(localPendingCallBack); } var localPendingCallBackWifiOnly = _lastPendingCallbackWifiOnly; if (localPendingCallBackWifiOnly != null && networkreachability == NetworkReachability.ReachableViaLocalAreaNetwork) { _lastPendingCallbackWifiOnly = null; StartSynchronizeInternalAsync(localPendingCallBackWifiOnly); } }
private bool MergeRemoteRecords(ISyncCallback callback, DatasetUpdates datasetUpdates) { var conflicts = new List <SyncConflict>(); var remoteUpdates = new List <Record>(); foreach (var remoteRecord in datasetUpdates.Records) { var localRecord = _local.GetRecord(IdentityId, Name, remoteRecord.Key); if (localRecord == null) { remoteUpdates.Add(remoteRecord); continue; } if (remoteRecord.SyncRegion != localRecord.SyncRegion) // always a conflict if region is different. { conflicts.Add(new SyncConflict(remoteRecord, localRecord)); continue; } if (remoteRecord.SyncCount <= localRecord.SyncCount) { // ignore remote record if we know for sure remote record is older. continue; } if (localRecord.IsDirty) { conflicts.Add(new SyncConflict(remoteRecord, localRecord)); } else { remoteUpdates.Add(remoteRecord); } } _logger.DebugFormat("INTERNAL LOG - {0} records in conflict", conflicts.Count); if (conflicts.Count != 0 && !callback.OnConflict(this, conflicts)) { var e = new SyncConflictingException(); if (Logger.LoggingConfig.LogInnerMostError) { _logger.Error(e, "INTERNAL LOG - Conflict resolution failed/cancelled."); } callback.OnError(this, e); return(false); } if (remoteUpdates.Count != 0) { _logger.DebugFormat("INTERNAL LOG - Save {0} records to local", remoteUpdates.Count); _local.PutRecords(IdentityId, Name, remoteUpdates); } _local.UpdateLastSyncRevision(IdentityId, Name, datasetUpdates.SyncRevisions); _logger.DebugFormat("INTERNAL LOG - Update SyncRevision of Dataset to {0}", SdkUtils.ConvertSyncRevisionToString(datasetUpdates.SyncRevisions)); return(true); }
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); }); }); }