Amazon.CognitoSync.SyncManager.Dataset.RunSyncOperationAsync C# (CSharp) Method

RunSyncOperationAsync() private method

private RunSyncOperationAsync ( int retry, CancellationToken cancellationToken ) : System.Threading.Task
retry int
cancellationToken System.Threading.CancellationToken
return System.Threading.Task
        private async Task RunSyncOperationAsync(int retry, CancellationToken cancellationToken)
#endif
        {
            long lastSyncCount = Local.GetLastSyncCount(IdentityId, DatasetName);
#if !(BCL35 || UNITY)
            ExceptionDispatchInfo capturedException = null;
#endif
            // if dataset is deleted locally, push it to remote
            if (lastSyncCount == -1)
            {
                try
                {
#if BCL35||UNITY
                    Remote.DeleteDataset(DatasetName);
#else
                    await Remote.DeleteDatasetAsync(DatasetName, cancellationToken).ConfigureAwait(false);
#endif
                }
                catch (DatasetNotFoundException)
                {
                    //Ignore the exception here, since the dataset was local only
                }
                catch (Exception e)
                {
                    _logger.InfoFormat("{0} , dataset : {1}", e.Message, this.DatasetName);
                    EndSynchronizeAndCleanup();
#if UNITY
                    FireSyncFailureEvent(e, options);
#else
                    FireSyncFailureEvent(e);
#endif 
                    return;
                }

                Local.PurgeDataset(IdentityId, DatasetName);
                _logger.InfoFormat("OnSyncSuccess: dataset delete is pushed to remote - {0}", this.DatasetName);
                EndSynchronizeAndCleanup();
#if UNITY
                FireSyncSuccessEvent(new List<Record>(), options);
#else
                FireSyncSuccessEvent(new List<Record>());
#endif
                return;
            }

            // get latest modified records from remote
            _logger.InfoFormat("Get latest modified records since {0} for dataset {1}", lastSyncCount, this.DatasetName);
            DatasetUpdates datasetUpdates = null;
            try
            {
#if BCL35||UNITY
                datasetUpdates = Remote.ListUpdates(DatasetName, lastSyncCount);
#else
                datasetUpdates = await Remote.ListUpdatesAsync(DatasetName, lastSyncCount, cancellationToken).ConfigureAwait(false);
#endif
            }
            catch (Exception listUpdatesException)
            {
                _logger.Error(listUpdatesException, string.Empty);
                EndSynchronizeAndCleanup();
#if UNITY
                FireSyncFailureEvent(listUpdatesException, options);
#else
                FireSyncFailureEvent(listUpdatesException);
#endif
                return;
            }

            if (datasetUpdates != null && datasetUpdates.MergedDatasetNameList.Count != 0 && this.OnDatasetMerged != null)
            {
                bool resume = this.OnDatasetMerged(this, datasetUpdates.MergedDatasetNameList);
                if (resume)
                {
                    if (retry == 0)
                    {
                        EndSynchronizeAndCleanup();
#if UNITY
                        FireSyncFailureEvent(new SyncManagerException("Out of retries"), options);
#else
                        FireSyncFailureEvent(new SyncManagerException("Out of retries"));
#endif
                    }
                    else
                    {
#if BCL35
                        this.RunSyncOperation(--retry);
#elif UNITY
                        this.RunSyncOperation(--retry, options);
#else
                        await this.RunSyncOperationAsync(--retry, cancellationToken).ConfigureAwait(false);
#endif
                    }
                    return;
                }
                else
                {
                    _logger.InfoFormat("OnSyncFailure: Manual Cancel");
                    EndSynchronizeAndCleanup();
#if UNITY
                    FireSyncFailureEvent(new SyncManagerException("Manual cancel"), options);
#else
                    FireSyncFailureEvent(new SyncManagerException("Manual cancel"));
#endif
                    return;
                }
            }

            // if the dataset doesn't exist or is deleted, trigger onDelete
            if (lastSyncCount != 0 && !datasetUpdates.Exists
                || datasetUpdates.Deleted && this.OnDatasetDeleted != null)
            {
                bool resume = this.OnDatasetDeleted(this);
                if (resume)
                {
                    // remove both records and metadata
                    Local.DeleteDataset(IdentityId, DatasetName);
                    Local.PurgeDataset(IdentityId, DatasetName);
                    _logger.InfoFormat("OnSyncSuccess");
                    EndSynchronizeAndCleanup();
#if UNITY
                    FireSyncSuccessEvent(new List<Record>(), options);
#else
                    FireSyncSuccessEvent(new List<Record>());
#endif
                    return;
                }
                else
                {
                    _logger.InfoFormat("OnSyncFailure");
                    EndSynchronizeAndCleanup();
#if UNITY
                    FireSyncFailureEvent(new SyncManagerException("Manual cancel"), options);
#else
                    FireSyncFailureEvent(new SyncManagerException("Manual cancel"));
#endif
                    return;
                }
            }
            lastSyncCount = datasetUpdates.SyncCount;

            List<Record> remoteRecords = datasetUpdates.Records;
            if (remoteRecords.Count != 0)
            {
                // if conflict, prompt developer/user with callback
                List<SyncConflict> conflicts = new List<SyncConflict>();
                List<Record> conflictRecords = new List<Record>();
                foreach (Record remoteRecord in remoteRecords)
                {
                    Record localRecord = Local.GetRecord(IdentityId,
                                                          DatasetName,
                                                          remoteRecord.Key);
                    // only when local is changed and its value is different
                    if (localRecord != null && localRecord.IsModified
                        && !StringUtils.Equals(localRecord.Value, remoteRecord.Value))
                    {
                        conflicts.Add(new SyncConflict(remoteRecord, localRecord));
                        conflictRecords.Add(remoteRecord);
                    }
                }
                // retaining only non-conflict records
                remoteRecords.RemoveAll(t => conflictRecords.Contains(t));

                if (conflicts.Count > 0)
                {
                    _logger.InfoFormat("{0} records in conflict!", conflicts.Count);
                    bool syncConflictResult = false;
                    if (this.OnSyncConflict == null)
                    {
                        // delegate is not implemented so the conflict resolution is applied
                        syncConflictResult = this.ResolveConflictsWithDefaultPolicy(conflicts);
                    }
                    else
                    {
                        syncConflictResult = this.OnSyncConflict(this, conflicts);
                    }
                    if (!syncConflictResult)
                    {
                        _logger.InfoFormat("User cancelled conflict resolution");
                        EndSynchronizeAndCleanup();
#if UNITY
                        FireSyncFailureEvent(new OperationCanceledException("User cancelled conflict resolution"), options);
#else
                        FireSyncFailureEvent(new OperationCanceledException("User cancelled conflict resolution"));
#endif
                        return;
                    }
                }

                // save to local
                if (remoteRecords.Count > 0)
                {
                    _logger.InfoFormat("Save {0} records to local", remoteRecords.Count);
                    Local.PutRecords(IdentityId, DatasetName, remoteRecords);
                }


                // new last sync count
                _logger.InfoFormat("Updated sync count {0}", datasetUpdates.SyncCount);
                Local.UpdateLastSyncCount(IdentityId, DatasetName,
                                          datasetUpdates.SyncCount);
            }

            // push changes to remote
            List<Record> localChanges = this.ModifiedRecords;
            long minPatchSyncCount = lastSyncCount;
            foreach (Record r in localChanges)
            {
                //track the max sync count
                if (r.SyncCount < minPatchSyncCount)
                {
                    minPatchSyncCount = r.SyncCount;
                }
            }
            if (localChanges.Count != 0)
            {
                _logger.InfoFormat("Push {0} records to remote", localChanges.Count);

                try
                {
#if BCL35 || UNITY
                    List<Record> result = Remote.PutRecords(DatasetName, localChanges, datasetUpdates.SyncSessionToken);
#else
                    List<Record> result = await Remote.PutRecordsAsync(DatasetName, localChanges, datasetUpdates.SyncSessionToken, cancellationToken).ConfigureAwait(false);
#endif

                    // update local meta data
                    Local.ConditionallyPutRecords(IdentityId, DatasetName, result, localChanges);

                    // verify the server sync count is increased exactly by one, aka no
                    // other updates were made during this update.
                    long newSyncCount = 0;
                    foreach (Record record in result)
                    {
                        newSyncCount = newSyncCount < record.SyncCount
                            ? record.SyncCount
                                : newSyncCount;
                    }
                    if (newSyncCount == lastSyncCount + 1)
                    {
                        _logger.InfoFormat("Updated sync count {0}", newSyncCount);
                        Local.UpdateLastSyncCount(IdentityId, DatasetName,
                                                  newSyncCount);
                    }

                    _logger.InfoFormat("OnSyncSuccess");
                    EndSynchronizeAndCleanup();
#if UNITY
                    FireSyncSuccessEvent(remoteRecords, options);
#else
                    FireSyncSuccessEvent(remoteRecords);
#endif
                    return;

                }
                catch (DataConflictException e)
                {
                    _logger.InfoFormat("Conflicts detected when pushing changes to remote: {0}", e.Message);
                    if (retry == 0)
                    {
                        EndSynchronizeAndCleanup();
#if UNITY
                        FireSyncFailureEvent(e, options);
#else
                        FireSyncFailureEvent(e);
#endif
                    }
                    else
                    {
                        //it's possible there is a local dirty record with a stale sync count this will fix it
                        if (lastSyncCount > minPatchSyncCount)
                        {
                            Local.UpdateLastSyncCount(IdentityId, DatasetName, minPatchSyncCount);
                        }
#if BCL35
                        RunSyncOperation(--retry);
                    }
                    return;
                }
#elif UNITY
                        RunSyncOperation(--retry, options);
                    }
                    return;
                }
#else