internal FileSystemUpdateFailedEventArgs(ISyncProvider fileSystem, FileSystemChange change, Exception exception)
 {
     this.FileSystem = fileSystem;
     this.Entry = change.Entry;
     this.ChangeType = change.ChangeType;
     this.Exception = exception;
 }
Beispiel #2
0
        private IEnumerable <SyncProfileOption> GetProfileOptions(ISyncProvider provider, SyncTarget target, User user)
        {
            var hasQuality = provider as IHasSyncQuality;

            if (hasQuality != null)
            {
                return(hasQuality.GetProfileOptions(target));
            }

            var list = new List <SyncProfileOption>();

            list.Add(new SyncProfileOption
            {
                Name                 = "Original",
                Id                   = "Original",
                Description          = "Syncs original files as-is.",
                EnableQualityOptions = false
            });

            if (user == null || user.Policy.EnableSyncTranscoding)
            {
                list.Add(new SyncProfileOption
                {
                    Name        = "Baseline",
                    Id          = "baseline",
                    Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio."
                });

                list.Add(new SyncProfileOption
                {
                    Name        = "General",
                    Id          = "general",
                    Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.",
                    IsDefault   = true
                });
            }

            return(list);
        }
Beispiel #3
0
        public void ApplyChangesWhile(ISyncProvider fileSystem, IEnumerable<FileSystemChange> changes, Func<bool> stopCheck)
        {
            foreach (var change in changes)
            {
                if (stopCheck() == true)
                    break;

                FileSystemEntry newEntry = null;

                try
                {
                    if (change.ChangeType == FileSystemChangeType.Create)
                    {
                        newEntry = fileSystem.Create(change.Entry);
                    }
                    else if (change.ChangeType == FileSystemChangeType.Delete)
                    {
                        fileSystem.Delete(change.Entry);
                    }
                    else if (change.ChangeType == FileSystemChangeType.Overwrite)
                    {
                        fileSystem.Delete(change.Entry);
                        newEntry = fileSystem.Create(change.Entry);
                    }

                    if (newEntry != null && change.Entry.Created != null)
                        newEntry.SetCreationTime(change.Entry.Created.Value);

                    if (newEntry != null && change.Entry.Modified != null)
                        newEntry.SetModificationTime(change.Entry.Modified.Value);

                    NotifyFileSystemUpdated(fileSystem, change);
                }
                catch (Exception ex)
                {
                    NotifyFileSystemUpdateFailed(fileSystem, change, ex);
                }
            }
        }
Beispiel #4
0
 private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
 {
     return provider.GetSyncTargets(userId).Select(i => new SyncTarget
     {
         Name = i.Name,
         Id = GetSyncTargetId(provider, i)
     });
 }
Beispiel #5
0
        private IEnumerable<SyncProfileOption> GetProfileOptions(ISyncProvider provider, SyncTarget target, User user)
        {
            var hasQuality = provider as IHasSyncQuality;
            if (hasQuality != null)
            {
                return hasQuality.GetProfileOptions(target);
            }

            var list = new List<SyncProfileOption>();

            list.Add(new SyncProfileOption
            {
                Name = "Original",
                Id = "Original",
                Description = "Syncs original files as-is.",
                EnableQualityOptions = false
            });

            if (user == null || user.Policy.EnableSyncTranscoding)
            {
                list.Add(new SyncProfileOption
                {
                    Name = "Baseline",
                    Id = "baseline",
                    Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio."
                });

                list.Add(new SyncProfileOption
                {
                    Name = "General",
                    Id = "general",
                    Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.",
                    IsDefault = true
                });
            }

            return list;
        }
Beispiel #6
0
        private SyncJobOptions GetSyncJobOptions(ISyncProvider provider, SyncTarget target, string profile, string quality)
        {
            var hasProfile = provider as IHasSyncQuality;

            if (hasProfile != null)
            {
                return hasProfile.GetSyncJobOptions(target, profile, quality);
            }

            return GetDefaultSyncJobOptions(profile, quality);
        }
Beispiel #7
0
        private async Task Test1(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            var localStoreId = await localSyncProvider.GetStoreIdAsync();

            var remoteStoreId = await remoteSyncProvider.GetStoreIdAsync();

            var initialLocalSet = await localSyncProvider.GetChangesAsync(remoteStoreId);

            var initialRemoteSet = await remoteSyncProvider.GetChangesAsync(localStoreId);

            Assert.IsNotNull(initialRemoteSet);
            Assert.IsNotNull(initialRemoteSet.Items);
            Assert.AreEqual(0, initialRemoteSet.Items.Count);

            Assert.IsNotNull(initialLocalSet);
            Assert.IsNotNull(initialLocalSet.Items);
            Assert.AreEqual(0, initialLocalSet.Items.Count);

            var newUser = new User()
            {
                Email = "*****@*****.**", Name = "User1", Created = new DateTime(2019, 1, 1)
            };

            remoteDb.Users.Add(newUser);
            await remoteDb.SaveChangesAsync();

            var changeSetAfterUserAdd = await remoteSyncProvider.GetChangesAsync(localStoreId);

            Assert.IsNotNull(changeSetAfterUserAdd);
            Assert.IsNotNull(changeSetAfterUserAdd.Items);
            Assert.AreEqual(1, changeSetAfterUserAdd.Items.Count);
            Assert.AreEqual(ChangeType.Insert, changeSetAfterUserAdd.Items[0].ChangeType);
            Assert.AreEqual(newUser.Email, changeSetAfterUserAdd.Items[0].Values["Email"]);
            Assert.AreEqual(newUser.Name, changeSetAfterUserAdd.Items[0].Values["Name"]);

            var finalLocalAnchor = await localSyncProvider.ApplyChangesAsync(changeSetAfterUserAdd);

            Assert.IsNotNull(finalLocalAnchor);

            //try to apply same changeset result in an exception
            var exception = await Assert.ThrowsExceptionAsync <InvalidSyncOperationException>(() => localSyncProvider.ApplyChangesAsync(changeSetAfterUserAdd));

            Assert.IsNotNull(exception);

            newUser.Created = new DateTime(2018, 1, 1);
            await remoteDb.SaveChangesAsync();

            {
                //after saved changes version should be updated as well at 2
                var changeSetAfterUserEdit = await remoteSyncProvider.GetChangesAsync(localStoreId);

                Assert.IsNotNull(changeSetAfterUserEdit);
                Assert.IsNotNull(changeSetAfterUserEdit.Items);
                Assert.AreEqual(1, changeSetAfterUserEdit.Items.Count);
                Assert.AreEqual(newUser.Email, changeSetAfterUserEdit.Items[0].Values["Email"]);
                Assert.AreEqual(newUser.Name, changeSetAfterUserEdit.Items[0].Values["Name"]);
                Assert.AreEqual(newUser.Created, changeSetAfterUserEdit.Items[0].Values["Created"]);
            }

            {
                //now let's change same record in local database and try to apply changes to remote db
                //this should result in a conflict
                var newUserInLocalDb = await localDb.Users.FirstAsync(_ => _.Name == newUser.Name);

                newUserInLocalDb.Name = "modified-name";
                await localDb.SaveChangesAsync();

                //get changes from local db
                var localChangeSet = await localSyncProvider.GetChangesAsync(remoteStoreId);

                Assert.IsNotNull(localChangeSet);

                //try to apply changes to remote provider
                var anchorAfterChangesAppliedFromLocalProvider =
                    await remoteSyncProvider.ApplyChangesAsync(localChangeSet);

                //given we didn't provide a resolution function for the conflict provider just skip
                //to apply the changes from local db
                //so nothing should be changed in remote db
                Assert.IsNotNull(anchorAfterChangesAppliedFromLocalProvider);

                var userNotChangedInRemoteDb = await remoteDb.Users.FirstAsync(_ => _.Email == newUser.Email);

                Assert.IsNotNull(userNotChangedInRemoteDb);
                Assert.AreEqual(newUser.Name, userNotChangedInRemoteDb.Name);
                Assert.AreEqual(newUser.Created, userNotChangedInRemoteDb.Created);

                //ok now try apply changes but forcing any write on remote store on conflict
                anchorAfterChangesAppliedFromLocalProvider =
                    await remoteSyncProvider.ApplyChangesAsync(localChangeSet,
                                                               (item) =>
                {
                    //assert that conflict occurred on item we just got from local db
                    Assert.IsNotNull(item);
                    Assert.AreEqual(newUserInLocalDb.Email, item.Values["Email"]);
                    Assert.AreEqual(newUserInLocalDb.Name, item.Values["Name"]);
                    Assert.AreEqual(ChangeType.Update, item.ChangeType);

                    //force write in remote store
                    return(ConflictResolution.ForceWrite);
                });

                //now we should have a new version  (+1)
                Assert.IsNotNull(anchorAfterChangesAppliedFromLocalProvider);

                //and local db changes should be applied to remote db
                var userChangedInRemoteDb = await remoteDb.Users.AsNoTracking().FirstAsync(_ => _.Email == newUser.Email);

                Assert.IsNotNull(userChangedInRemoteDb);
                Assert.AreEqual(newUserInLocalDb.Name, userChangedInRemoteDb.Name);
                Assert.AreEqual(newUserInLocalDb.Created, userChangedInRemoteDb.Created);
            }

            {
                //now let's try to update a deleted record
                remoteDb.Users.Remove(newUser);
                await remoteDb.SaveChangesAsync();

                var newUserInLocalDb = await localDb.Users.FirstAsync(_ => _.Email == newUser.Email);

                var localChangeSet = await localSyncProvider.GetChangesAsync(remoteStoreId);

                Assert.IsNotNull(localChangeSet);

                //try to apply changes to remote provider
                var anchorAfterChangesAppliedFromLocalProvider =
                    await remoteSyncProvider.ApplyChangesAsync(localChangeSet);

                //given we didn't provide a resolution function for the conflict provider just skip
                //to apply the changes from local db
                //so nothing should be changed in remote db
                Assert.IsNotNull(anchorAfterChangesAppliedFromLocalProvider);

                //user should not be present
                var userNotChangedInRemoteDb = await remoteDb.Users.FirstOrDefaultAsync(_ => _.Email == newUser.Email);

                Assert.IsNull(userNotChangedInRemoteDb);

                //ok now try apply changes but forcing any write on remote store on conflict
                anchorAfterChangesAppliedFromLocalProvider =
                    await remoteSyncProvider.ApplyChangesAsync(localChangeSet,
                                                               (item) =>
                {
                    //assert that conflict occurred on item we just got from local db
                    Assert.IsNotNull(item);
                    Assert.AreEqual(newUserInLocalDb.Email, item.Values["Email"]);
                    Assert.AreEqual(newUserInLocalDb.Name, item.Values["Name"]);
                    Assert.AreEqual(ChangeType.Update, item.ChangeType);

                    //force write in remote store
                    return(ConflictResolution.ForceWrite);
                });

                //now we should have a new version  (+1)
                Assert.IsNotNull(anchorAfterChangesAppliedFromLocalProvider);

                //and local db changes should be applied to remote db
                var userChangedInRemoteDb = await remoteDb.Users.AsNoTracking().FirstAsync(_ => _.Email == newUser.Email);

                Assert.IsNotNull(userChangedInRemoteDb);
                Assert.AreEqual(newUserInLocalDb.Name, userChangedInRemoteDb.Name);
                Assert.AreEqual(new DateTime(2019, 1, 1), userChangedInRemoteDb.Created);
            }
        }
Beispiel #8
0
 public SyncAgent(ISyncProvider localSyncProvider, ISyncProvider remoteSyncProvider)
 {
     LocalSyncProvider  = localSyncProvider ?? throw new ArgumentNullException(nameof(localSyncProvider));
     RemoteSyncProvider = remoteSyncProvider ?? throw new ArgumentNullException(nameof(remoteSyncProvider));
 }
Beispiel #9
0
 //
 // GET: /Series/
 public SeriesController(ISyncProvider syncProvider, ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider)
 {
     _seriesProvider = seriesProvider;
     _episodeProvider = episodeProvider;
     _syncProvider = syncProvider;
 }
        // Token: 0x060010EA RID: 4330 RVA: 0x00045E10 File Offset: 0x00044010
        public SyncCalendarResponse Execute(out IFolderSyncState newSyncState, out IList <KeyValuePair <StoreId, LocalizedException> > caughtExceptions)
        {
            ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar.Execute: Start");
            Stopwatch stopwatch = Stopwatch.StartNew();

            caughtExceptions = new List <KeyValuePair <StoreId, LocalizedException> >();
            MailboxSyncProviderFactory  mailboxSyncProviderFactory        = new MailboxSyncProviderFactory(this.session, this.folderId);
            HashSet <StoreId>           syncItemsHashSet                  = new HashSet <StoreId>();
            List <SyncCalendarItemType> updatedItemsList                  = new List <SyncCalendarItemType>();
            List <SyncCalendarItemType> recurrenceMastersWithInstances    = new List <SyncCalendarItemType>();
            List <SyncCalendarItemType> recurrenceMastersWithoutInstances = new List <SyncCalendarItemType>();
            Dictionary <StoreId, SyncCalendarItemType> unchangedRecurrenceMastersWithInstances = new Dictionary <StoreId, SyncCalendarItemType>();
            List <StoreId> deletedItemsList = new List <StoreId>();
            bool           flag             = true;
            CalendarViewQueryResumptionPoint calendarViewQueryResumptionPoint = null;

            using (ISyncProvider syncProvider = mailboxSyncProviderFactory.CreateSyncProvider(null))
            {
                newSyncState = this.syncState.CreateFolderSyncState(this.folderId, syncProvider);
                ExDateTime value;
                if (CalendarSyncState.IsEmpty(this.syncState) || this.syncState.OldWindowEnd == null || this.windowStart >= this.syncState.OldWindowEnd.Value)
                {
                    ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar.InternalExecute: Requesting catch-up sync state from ICS");
                    newSyncState.Watermark = syncProvider.GetMaxItemWatermark(newSyncState.Watermark);
                    value = this.windowStart;
                }
                else
                {
                    value = this.syncState.OldWindowEnd.Value;
                }
                if (newSyncState.Watermark != null)
                {
                    int num  = this.maxChangesReturned;
                    int num2 = 0;
                    int num3 = 0;
                    if (this.windowEnd > value)
                    {
                        calendarViewQueryResumptionPoint = this.DoQuerySync(syncItemsHashSet, updatedItemsList, recurrenceMastersWithInstances, unchangedRecurrenceMastersWithInstances, value, this.windowEnd, num, caughtExceptions, out num2);
                        flag = !calendarViewQueryResumptionPoint.IsEmpty;
                        num  = this.CalculateRemainingItemsCount(num, num2);
                        ExTraceGlobals.SyncCalendarTracer.TraceDebug <int, int, bool>((long)this.GetHashCode(), "XsoSyncCalendar.DoQuerySync added {0} items to the sync response. Remaining Items: {1}; More Available: {2}", num2, num, flag);
                    }
                    if (num != 0)
                    {
                        flag = this.DoIcsSync(syncItemsHashSet, updatedItemsList, recurrenceMastersWithInstances, recurrenceMastersWithoutInstances, unchangedRecurrenceMastersWithInstances, deletedItemsList, newSyncState.Watermark, syncProvider, num, caughtExceptions, out num3);
                        ExTraceGlobals.SyncCalendarTracer.TraceDebug <int, bool>((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSync added {0} items to the sync response. More Available: {1}", num3, flag);
                    }
                    else
                    {
                        ExTraceGlobals.SyncCalendarTracer.TraceDebug <int, int>((long)this.GetHashCode(), "XsoSyncCalendar; Skipping ICS sync, since we've reached the max items requested (Requested: {0}; Actual: {1}).", this.maxChangesReturned, num2);
                    }
                    ExTraceGlobals.SyncCalendarTracer.TraceDebug <int, int>((long)this.GetHashCode(), "XsoSyncCalendar; Finished fetching items. Total items synced: {0}; Max requested: {1}", num2 + num3, this.maxChangesReturned);
                }
                else
                {
                    flag = false;
                    ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar; Nothing to sync. The specified folder is empty.");
                }
            }
            SyncCalendarResponse result = this.AssembleResponse(flag ? calendarViewQueryResumptionPoint : null, flag ? this.syncState.OldWindowEnd : new ExDateTime?(this.windowEnd), updatedItemsList, recurrenceMastersWithInstances, recurrenceMastersWithoutInstances, unchangedRecurrenceMastersWithInstances, deletedItemsList, !flag);

            stopwatch.Stop();
            ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar.InternalExecute: End " + stopwatch.ElapsedMilliseconds);
            return(result);
        }
        // Token: 0x060010ED RID: 4333 RVA: 0x00046494 File Offset: 0x00044694
        private bool DoIcsSync(HashSet <StoreId> syncItemsHashSet, IList <SyncCalendarItemType> updatedItemsList, IList <SyncCalendarItemType> recurrenceMastersWithInstances, IList <SyncCalendarItemType> recurrenceMastersWithoutInstances, IDictionary <StoreId, SyncCalendarItemType> unchangedRecurrenceMastersWithInstances, IList <StoreId> deletedItemsList, ISyncWatermark watermark, ISyncProvider syncProvider, int maxCount, IList <KeyValuePair <StoreId, LocalizedException> > caughtExceptions, out int addedItems)
        {
            ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSync: Start");
            addedItems = 0;
            int num = (maxCount == 1) ? 1 : ((int)(0.8 * (double)maxCount));
            Dictionary <ISyncItemId, ServerManifestEntry> dictionary = new Dictionary <ISyncItemId, ServerManifestEntry>();
            bool flag = false;

            do
            {
                ExTraceGlobals.SyncCalendarTracer.TraceDebug <int>((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSync: Requesting {0} changes from ICS", 100);
                int numOperations = Math.Min(num - addedItems, 100);
                flag = syncProvider.GetNewOperations(watermark, null, true, numOperations, null, dictionary);
                ExTraceGlobals.SyncCalendarTracer.TraceDebug <int>((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSync: Received {0} entries from ICS", dictionary.Count);
                foreach (ServerManifestEntry serverManifestEntry in dictionary.Values)
                {
                    StoreObjectId id = (StoreObjectId)serverManifestEntry.Id.NativeId;
                    switch (serverManifestEntry.ChangeType)
                    {
                    case ChangeType.Add:
                    case ChangeType.Change:
                        addedItems += this.AddNewOrChangedItems(id, updatedItemsList, recurrenceMastersWithInstances, recurrenceMastersWithoutInstances, unchangedRecurrenceMastersWithInstances, deletedItemsList, syncItemsHashSet, caughtExceptions);
                        continue;

                    case ChangeType.Delete:
                        addedItems += this.AddDeletedItem(id, syncItemsHashSet, deletedItemsList);
                        continue;
                    }
                    ExTraceGlobals.SyncCalendarTracer.TraceWarning <ChangeType>((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSyncs unknown/unexpected sync change type {0}", serverManifestEntry.ChangeType);
                }
            }while (flag && num > addedItems);
            ExTraceGlobals.SyncCalendarTracer.TraceDebug((long)this.GetHashCode(), "XsoSyncCalendar.DoIcsSync: End");
            return(flag);
        }
Beispiel #12
0
 public void InitializeAllItemsInFilter(ISyncProvider syncProvider)
 {
     this.entriesInFilter.Clear();
     syncProvider.GetNewOperations(syncProvider.CreateNewWatermark(), null, false, -1, this.filter, this.entriesInFilter);
 }
Beispiel #13
0
 private void NotifyFileSystemUpdateFailed(ISyncProvider fileSystem, FileSystemChange change, Exception ex)
 {
     if (FileSystemUpdateFailed != null)
         FileSystemUpdateFailed(this, new FileSystemUpdateFailedEventArgs(fileSystem, change, ex));
 }
Beispiel #14
0
 private void NotifyFileSystemUpdated(ISyncProvider fileSystem, FileSystemChange change)
 {
     if (FileSystemUpdated != null)
         FileSystemUpdated(this, new FileSystemUpdatedEventArgs(fileSystem, change));
 }
Beispiel #15
0
 private string GetSyncProviderId(ISyncProvider provider)
 {
     return (provider.GetType().Name).GetMD5().ToString("N");
 }
Beispiel #16
0
        /// <summary>
        /// Sets the source sync provider.
        /// </summary>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="syncAgent">The sync agent.</param>
        /// <param name="syncProvider">The source sync provider of the sync agent.</param>
        /// <returns></returns>
        public static ISyncAgent <TKey, TItem> SetSourceProvider <TKey, TItem>(this ISyncAgent <TKey, TItem> syncAgent, ISyncProvider <TItem> syncProvider)
        {
            syncAgent.SourceProvider = syncProvider;

            return(syncAgent);
        }
Beispiel #17
0
        /// <summary>
        /// Sets the destination sync provider.
        /// </summary>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="syncAgent">The sync agent.</param>
        /// <param name="syncProvider">The destination sync provider of the sync agent.</param>
        /// <returns></returns>
        public static ISyncAgent <TKey, TItem> SetDestinationProvider <TKey, TItem>(this ISyncAgent <TKey, TItem> syncAgent, ISyncProvider <TItem> syncProvider)
        {
            syncAgent.DestinationProvider = syncProvider;

            return(syncAgent);
        }
Beispiel #18
0
        private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
        {
            var providerId = GetSyncProviderId(provider);

            return provider.GetSyncTargets().Select(i => new SyncTarget
            {
                Name = i.Name,
                Id = providerId + "-" + i.Id
            });
        }
Beispiel #19
0
 public TypeConfiguration <U> With(ISyncProvider <U> provider)
 {
     TypeProvider.SyncProvider = provider;
     return(this);
 }
 // Token: 0x060010E4 RID: 4324
 public abstract IFolderSyncState CreateFolderSyncState(StoreObjectId folderObjectId, ISyncProvider syncProvider);
Beispiel #21
0
        private async Task Test2(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            var localStoreId = await localSyncProvider.GetStoreIdAsync();

            var remoteStoreId = await remoteSyncProvider.GetStoreIdAsync();

            var newUserLocal = new User()
            {
                Email = "*****@*****.**", Name = "user1", Created = new DateTime(2018, 1, 1)
            };

            newUserLocal.Posts.Add(new Post()
            {
                Title = "title of post", Content = "content of post", Claps = 2, Stars = 4.5f, Updated = new DateTime(2018, 3, 1)
            });
            localDb.Users.Add(newUserLocal);
            await localDb.SaveChangesAsync();

            //let's apply changes from local db to remote db
            var localChangeSet = await localSyncProvider.GetChangesAsync(remoteStoreId);

            Assert.IsNotNull(localChangeSet);
            Assert.AreEqual(2, localChangeSet.Items.Count);

            var remoteChangeSet = await remoteSyncProvider.GetChangesAsync(localStoreId);

            Assert.IsNotNull(remoteChangeSet);
            Assert.AreEqual(0, remoteChangeSet.Items.Count);

            var anchorAfterApplyChanges = await remoteSyncProvider.ApplyChangesAsync(localChangeSet);

            Assert.IsNotNull(anchorAfterApplyChanges);
            await localSyncProvider.SaveVersionForStoreAsync(remoteStoreId, localChangeSet.SourceAnchor.Version);


            var changeSetAfterApplyChangesToRemoteDb = await remoteSyncProvider.GetChangesAsync(localStoreId);

            Assert.IsNotNull(changeSetAfterApplyChangesToRemoteDb);
            Assert.AreEqual(2, changeSetAfterApplyChangesToRemoteDb.Items.Count);

            await localSyncProvider.ApplyChangesAsync(changeSetAfterApplyChangesToRemoteDb);

            await remoteSyncProvider.SaveVersionForStoreAsync(localStoreId, changeSetAfterApplyChangesToRemoteDb.SourceAnchor.Version);

            newUserLocal.Posts[0].Comments.Add(new Comment()
            {
                Content = "my first comment on post", Created = new DateTime(2018, 3, 2)
            });
            newUserLocal.Posts[0].Stars   = 4.0f;
            newUserLocal.Posts[0].Updated = new DateTime(2018, 3, 2);
            await localDb.SaveChangesAsync();

            localChangeSet = await localSyncProvider.GetChangesAsync(remoteStoreId);

            Assert.IsNotNull(localChangeSet);

            anchorAfterApplyChanges = await remoteSyncProvider.ApplyChangesAsync(localChangeSet);

            Assert.IsNotNull(anchorAfterApplyChanges);
            await localSyncProvider.SaveVersionForStoreAsync(remoteStoreId, localChangeSet.SourceAnchor.Version);

            var commentAdded = await remoteDb.Comments.FirstOrDefaultAsync(_ => _.Content == "my first comment on post");

            Assert.IsNotNull(commentAdded);
        }
Beispiel #22
0
 public FirstTimeFolderSync(ISyncProvider syncProvider, IFolderSyncState syncState, ConflictResolutionPolicy policy, bool deferStateModifications) : base(syncProvider, syncState, policy, deferStateModifications)
 {
 }
Beispiel #23
0
        private async Task TestSyncAgentMultipleRecordsOnSameTable(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            var syncAgent = new SyncAgent(localSyncProvider, remoteSyncProvider);
            //await syncAgent.InitializeAsync();
            await syncAgent.SynchronizeAsync();

            //create a user on server
            var remoteUser = new User()
            {
                Email = "*****@*****.**", Name = "user", Created = new DateTime(2018, 1, 1)
            };

            remoteDb.Users.Add(remoteUser);
            await remoteDb.SaveChangesAsync();

            //create a second user on server
            var remoteUser2 = new User()
            {
                Email = "*****@*****.**", Name = "user2", Created = new DateTime(2019, 1, 1)
            };

            remoteDb.Users.Add(remoteUser2);
            await remoteDb.SaveChangesAsync();

            //sync with remote server
            await syncAgent.SynchronizeAsync();

            //verify that new user is stored now locally too
            var localUser = await localDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user", localUser.Name);
            Assert.AreEqual(new DateTime(2018, 1, 1), localUser.Created);

            //verify that new second user is stored now locally too
            var localUser2 = await localDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user2", localUser2.Name);
            Assert.AreEqual(new DateTime(2019, 1, 1), localUser2.Created);

            localUser.Posts.Add(new Post()
            {
                Content = "This is first post from user 1",
                Updated = new DateTime(2019, 1, 1)
            });

            localUser.Posts.Add(new Post()
            {
                Content = "This is second post from user 1",
                Updated = new DateTime(2019, 1, 2)
            });

            localUser2.Posts.Add(new Post()
            {
                Content = "This is first post from user 2",
                Updated = DateTime.Now
            });
            await localDb.SaveChangesAsync();


            //create a third user on server
            var remoteUser3 = new User()
            {
                Email = "*****@*****.**", Name = "user3", Created = new DateTime(2019, 1, 1)
            };

            remoteDb.Users.Add(remoteUser3);
            await remoteDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync();

            localDb = localDb.Refresh();

            //verify that first user is still stored locally
            localUser = await localDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user", localUser.Name);
            Assert.AreEqual(new DateTime(2018, 1, 1), localUser.Created);

            //verify that second user is still stored locally
            localUser2 = await localDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user2", localUser2.Name);
            Assert.AreEqual(new DateTime(2019, 1, 1), localUser2.Created);

            //verify that new third user is stored locally now
            var localUser3 = await localDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user3", localUser3.Name);
            Assert.AreEqual(new DateTime(2019, 1, 1), localUser3.Created);

            //verify that user posts are still stored locally
            Assert.AreEqual("This is first post from user 1", localUser.Posts.OrderBy(_ => _.Updated).ToArray()[0].Content);
            Assert.AreEqual("This is second post from user 1", localUser.Posts.OrderBy(_ => _.Updated).ToArray()[1].Content);
            Assert.AreEqual("This is first post from user 2", localUser2.Posts.OrderBy(_ => _.Updated).ToArray()[0].Content);

            remoteDb = remoteDb.Refresh();

            //verify that first user is still stored remotely
            remoteUser = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user", remoteUser.Name);
            Assert.AreEqual(new DateTime(2018, 1, 1), remoteUser.Created);

            //verify that second user is still stored remotely
            remoteUser2 = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user2", remoteUser2.Name);
            Assert.AreEqual(new DateTime(2019, 1, 1), remoteUser2.Created);

            //verify that new third user still stored remotely
            remoteUser3 = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user3", remoteUser3.Name);
            Assert.AreEqual(new DateTime(2019, 1, 1), remoteUser3.Created);

            //verify that user posts are still stored remotely
            Assert.AreEqual("This is first post from user 1", remoteUser.Posts.OrderBy(_ => _.Updated).ToArray()[0].Content);
            Assert.AreEqual("This is second post from user 1", remoteUser.Posts.OrderBy(_ => _.Updated).ToArray()[1].Content);
            Assert.AreEqual(1, remoteUser2.Posts.Count);
            Assert.AreEqual("This is first post from user 2", remoteUser2.Posts.OrderBy(_ => _.Updated).ToArray()[0].Content);

            //now delete a post locally
            localDb.Posts.Remove(localUser2.Posts.First());
            await localDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh();

            remoteUser2 = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual(0, remoteUser2.Posts.Count);

            //now delete a post on server
            remoteDb.Posts.Remove(remoteUser.Posts[0]);
            await remoteDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync();

            localDb = localDb.Refresh();

            localUser = await localDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual(1, localUser.Posts.Count);


            remoteUser2.Posts.Add(new Post()
            {
                Content = "Post add to remote user while user is delete on local db",
                Updated = DateTime.Now
            });
            remoteUser2.Name = "edited name";
            await remoteDb.SaveChangesAsync();

            localDb.Users.Remove(localUser2);
            await localDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync(conflictResolutionOnLocalStore : ConflictResolution.ForceWrite);

            remoteDb = remoteDb.Refresh();
            localDb  = localDb.Refresh();

            //ensure that local db updated (local user 2 is present)
            localUser2 = await localDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            localUser2.Posts.Count.ShouldBe(1);
            localUser2.Posts[0].Content.ShouldBe("Post add to remote user while user is delete on local db");

            //ensure that remote db is updated
            remoteUser2 = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            remoteUser2.Posts.Count.ShouldBe(1);
            remoteUser2.Posts[0].Content.ShouldBe("Post add to remote user while user is delete on local db");
        }
Beispiel #24
0
        private async Task TestSyncAgent(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            var syncAgent = new SyncAgent(localSyncProvider, remoteSyncProvider);
            await syncAgent.SynchronizeAsync();

            //create a user on server
            var remoteUser = new User()
            {
                Email = "*****@*****.**", Name = "user", Created = new DateTime(2018, 1, 1)
            };

            remoteDb.Users.Add(remoteUser);
            await remoteDb.SaveChangesAsync();

            //sync with remote server
            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh(); //discard any cache data in ef

            //verify that new user is stored now locally too
            var localUser = await localDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user", localUser.Name);
            Assert.AreEqual(new DateTime(2018, 1, 1), localUser.Created);

            //create an article for user locally
            var localPost = new Post()
            {
                Content = "this is my first post", Title = "First Post", Updated = DateTime.Now.Date
            };

            localUser.Posts.Add(localPost);
            await localDb.SaveChangesAsync();

            //sync with remote server
            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh(); //discard any cache data in ef

            //verify that user on server and locally have the same post
            remoteUser = await remoteDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("user", remoteUser.Name);
            Assert.AreEqual(new DateTime(2018, 1, 1), remoteUser.Created);
            Assert.AreEqual(1, remoteUser.Posts.Count);
            var remotePost = remoteUser.Posts[0];

            Assert.AreEqual(localPost.Author.Name, remotePost.Author.Name);
            Assert.AreEqual(localPost.Content, remotePost.Content);
            Assert.AreEqual(localPost.Title, remotePost.Title);

            //now make a change to post content while claps it on server
            localPost.Content = "this is my my first post edited";
            await localDb.SaveChangesAsync();

            remotePost.Claps += 1;
            await remoteDb.SaveChangesAsync();

            //then sync
            await syncAgent.SynchronizeAsync(conflictResolutionOnLocalStore : ConflictResolution.ForceWrite);

            remoteDb = remoteDb.Refresh(); //discard any cache data in ef

            //verify that claps is 1 on both server and local stores
            //content is not changed because we set conflictResolutionOnLocalStore to ConflictResolution.ForceWrite
            //so server skipped our try to update content while local store forcely write data coming from server
            remoteUser = await remoteDb.Users.Include(_ => _.Posts).FirstAsync(_ => _.Email == "*****@*****.**");

            remotePost = remoteUser.Posts[0];
            Assert.AreEqual("user", remotePost.Author.Name);
            Assert.AreEqual("this is my first post", remotePost.Content);
            Assert.AreEqual(1, remotePost.Claps);

            localUser = await localDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            localPost = localUser.Posts[0];
            Assert.AreEqual("user", remotePost.Author.Name);
            Assert.AreEqual("this is my first post", remotePost.Content);
            Assert.AreEqual(1, remotePost.Claps);

            //so to handle this scenario (when a record is often edited on multiple devices)
            //we should take care of restoring any pending records (posts) locally
            //for example using a PendingPosts table (not synched)
        }
Beispiel #25
0
        private async Task TestSyncAgentWithInitialData(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            User remoteUser;

            remoteDb.Users.Add(remoteUser = new User()
            {
                Email = "*****@*****.**", Name = "User created before sync", Created = DateTime.Now
            });

            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a post created before sync of the client", Title = "Initial post of user 1", Claps = 1, Stars = 10
            });
            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a second post created before sync of the client", Title = "Initial post 2 of user 1", Claps = 2, Stars = 1
            });

            await remoteDb.SaveChangesAsync();

            await remoteSyncProvider.ApplyProvisionAsync();

            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a third post created before sync of the client but after applying provision to remote db", Title = "Initial post 3 of user 1", Claps = 3, Stars = 1
            });

            await remoteDb.SaveChangesAsync();

            var syncAgent = new SyncAgent(localSyncProvider, remoteSyncProvider);
            await syncAgent.SynchronizeAsync();

            var localUser = await localDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            localUser.ShouldNotBeNull();
            localUser.Email.ShouldBe("*****@*****.**");
            localUser.Name.ShouldBe("User created before sync");

            var localUserPosts = localUser.Posts.OrderBy(_ => _.Claps).ToList();

            localUserPosts.Count().ShouldBe(3);
            localUserPosts[0].Content.ShouldBe("This is a post created before sync of the client");
            localUserPosts[0].Title.ShouldBe("Initial post of user 1");
            localUserPosts[0].Claps.ShouldBe(1);
            localUserPosts[0].Stars.ShouldBe(10);

            localUserPosts[1].Content.ShouldBe("This is a second post created before sync of the client");
            localUserPosts[1].Title.ShouldBe("Initial post 2 of user 1");
            localUserPosts[1].Claps.ShouldBe(2);
            localUserPosts[1].Stars.ShouldBe(1);

            localUserPosts[2].Content.ShouldBe("This is a third post created before sync of the client but after applying provision to remote db");
            localUserPosts[2].Title.ShouldBe("Initial post 3 of user 1");
            localUserPosts[2].Claps.ShouldBe(3);
            localUserPosts[2].Stars.ShouldBe(1);

            await syncAgent.SynchronizeAsync();

            localUser.Posts.Add(new Post()
            {
                Content = "Post created on local db after first sync", Title = "Post created on local db", Claps = 4
            });
            localUserPosts[0].Title = "Post edited on local db";

            await localDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh();

            var remoteUserPosts = remoteDb.Posts.OrderBy(_ => _.Claps).ToList();

            remoteUserPosts.Count().ShouldBe(4);
            remoteUserPosts[0].Content.ShouldBe("This is a post created before sync of the client");
            //even if edited on localdb post that was synched as initial snapshot can't be modified on server
            remoteUserPosts[0].Title.ShouldBe("Initial post of user 1");
            remoteUserPosts[0].Claps.ShouldBe(1);
            remoteUserPosts[0].Stars.ShouldBe(10);

            remoteUserPosts[1].Content.ShouldBe("This is a second post created before sync of the client");
            remoteUserPosts[1].Title.ShouldBe("Initial post 2 of user 1");
            remoteUserPosts[1].Claps.ShouldBe(2);
            remoteUserPosts[1].Stars.ShouldBe(1);

            remoteUserPosts[2].Content.ShouldBe("This is a third post created before sync of the client but after applying provision to remote db");
            remoteUserPosts[2].Title.ShouldBe("Initial post 3 of user 1");
            remoteUserPosts[2].Claps.ShouldBe(3);
            remoteUserPosts[2].Stars.ShouldBe(1);

            remoteUserPosts[3].Content.ShouldBe("Post created on local db after first sync");
            remoteUserPosts[3].Title.ShouldBe("Post created on local db");
            remoteUserPosts[3].Claps.ShouldBe(4);
            remoteUserPosts[3].Stars.ShouldBe(0);
        }
Beispiel #26
0
        private IEnumerable<SyncQualityOption> GetQualityOptions(ISyncProvider provider, SyncTarget target, User user)
        {
            var hasQuality = provider as IHasSyncQuality;
            if (hasQuality != null)
            {
                var options = hasQuality.GetQualityOptions(target);

                if (user != null && !user.Policy.EnableSyncTranscoding)
                {
                    options = options.Where(i => i.IsOriginalQuality);
                }

                return options;
            }

            // Default options for providers that don't override
            return new List<SyncQualityOption>
            {
                new SyncQualityOption
                {
                    Name = "High",
                    Id = "high",
                    IsDefault = true
                },
                new SyncQualityOption
                {
                    Name = "Medium",
                    Id = "medium"
                },
                new SyncQualityOption
                {
                    Name = "Low",
                    Id = "low"
                },
                new SyncQualityOption
                {
                    Name = "Custom",
                    Id = "custom"
                }
            };
        }
Beispiel #27
0
        private async Task TestSyncAgentWithUpdatedRemoteDeletedLocal(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            #region Initialize remote data, sync local and verify

            User remoteUser;
            remoteDb.Users.Add(remoteUser = new User()
            {
                Email = "*****@*****.**", Name = "User created before sync", Created = DateTime.Now
            });

            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a post created before sync of the client",
                Title   = "Initial post of user 1",
                Claps   = 1,
                Stars   = 10
            });

            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a second post created before sync of the client",
                Title   = "Initial post 2 of user 1",
                Claps   = 2,
                Stars   = 1
            });

            remoteUser.Posts.Add(new Post()
            {
                Content = "This is a third post created before sync of the client",
                Title   = "Initial post 3 of user 1",
                Claps   = 3,
                Stars   = 1
            });

            await remoteDb.SaveChangesAsync();

            var syncAgent = new SyncAgent(localSyncProvider, remoteSyncProvider);
            await syncAgent.SynchronizeAsync();

            var localUser = await localDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            localUser.ShouldNotBeNull();
            localUser.Email.ShouldBe("*****@*****.**");
            localUser.Name.ShouldBe("User created before sync");

            var localUserPosts = localUser.Posts.OrderBy(_ => _.Claps).ToList();
            localUserPosts.Count().ShouldBe(3);
            localUserPosts[0].Content.ShouldBe("This is a post created before sync of the client");
            localUserPosts[0].Title.ShouldBe("Initial post of user 1");
            localUserPosts[0].Claps.ShouldBe(1);
            localUserPosts[0].Stars.ShouldBe(10);

            localUserPosts[1].Content.ShouldBe("This is a second post created before sync of the client");
            localUserPosts[1].Title.ShouldBe("Initial post 2 of user 1");
            localUserPosts[1].Claps.ShouldBe(2);
            localUserPosts[1].Stars.ShouldBe(1);

            localUserPosts[2].Content.ShouldBe("This is a third post created before sync of the client");
            localUserPosts[2].Title.ShouldBe("Initial post 3 of user 1");
            localUserPosts[2].Claps.ShouldBe(3);
            localUserPosts[2].Stars.ShouldBe(1);

            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh();

            var remoteUserPosts = remoteDb.Posts.OrderBy(_ => _.Claps).ToList();
            remoteUserPosts.Count().ShouldBe(3);
            remoteUserPosts[0].Content.ShouldBe("This is a post created before sync of the client");
            //even if edited on localdb post that was synched as initial snapshot can't be modified on server
            remoteUserPosts[0].Title.ShouldBe("Initial post of user 1");
            remoteUserPosts[0].Claps.ShouldBe(1);
            remoteUserPosts[0].Stars.ShouldBe(10);

            remoteUserPosts[1].Content.ShouldBe("This is a second post created before sync of the client");
            remoteUserPosts[1].Title.ShouldBe("Initial post 2 of user 1");
            remoteUserPosts[1].Claps.ShouldBe(2);
            remoteUserPosts[1].Stars.ShouldBe(1);

            remoteUserPosts[2].Content.ShouldBe("This is a third post created before sync of the client");
            remoteUserPosts[2].Title.ShouldBe("Initial post 3 of user 1");
            remoteUserPosts[2].Claps.ShouldBe(3);
            remoteUserPosts[2].Stars.ShouldBe(1);

            #endregion

            #region Remove a local record and verify

            var postToRemove = localUser.Posts[2];

            localDb.Posts.Remove(localUser.Posts[2]);
            await localDb.SaveChangesAsync();

            localUser = await localDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual(2, localUser.Posts.Count);

            #endregion

            #region Update a remote record

            var remotePost = remoteUser.Posts.First(p => p.Id == postToRemove.Id);
            remotePost.Content = "Updated remote for test.";

            remoteDb = remoteDb.Refresh();
            remoteDb.Posts.Update(remotePost);

            await remoteDb.SaveChangesAsync();

            remoteUser = await remoteDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual("Updated remote for test.", remoteUser.Posts.First(p => p.Id == postToRemove.Id).Content);

            #endregion

            #region Syncronize and verify the local database has the deleted record
            //I've delete a post on local database AND updated the same posts on rempte database
            //SynchronizeAsync() accepts 2 args remoteConflictResolutionFunc and localConflictResolutionFunc
            //that describe how agent should deal with conflits:
            //1) remoteConflictResolutionFunc: (itemInConflict) => ConflictResolution.Skip or simply remoteConflictResolution: ConflictResolution.Skip
            //   means that remote database should not apply the delete operation on post coming from local database
            //2) localConflictResolutionFunc: (itemInConflict) => ConflictResolution.ForceWrite or simply localConflictResolutionFunc: ConflictResolution.ForceWrite
            //   means that local datase should update the local post that was updated from remote db and since the record doesn't exist anymore it actually means insert
            //   the post record again with data coming from server

            await syncAgent.SynchronizeAsync();

            //this above call is the same as this:
            // await syncAgent.SynchronizeAsync(conflictResolutionOnRemoteStore: ConflictResolution.Skip, conflictResolutionOnLocalStore: ConflictResolution.ForceWrite);
            //Thanks to Mike Perrenoud I've found that by default await syncAgent.SynchronizeAsync() was instead defaulted to
            // await syncAgent.SynchronizeAsync(conflictResolutionOnRemoteStore: ConflictResolution.Skip, conflictResolutionOnLocalStore: ConflictResolution.Skip);
            // causing this test to fail

            // following code allows to enumerate any item in conflict and take appropriate action for each of them:
            //await syncAgent.SynchronizeAsync(
            //    remoteConflictResolutionFunc: (itemInConflict) =>
            //    {
            //        itemInConflict.ChangeType.ShouldBe(ChangeType.Delete);
            //        itemInConflict.TableName.ShouldBe("Posts");
            //        itemInConflict.Values["Id"].Value = postToRemove.Id;
            //        return ConflictResolution.Skip;
            //    },
            //    localConflictResolutionFunc: (itemInConflict) =>
            //    {
            //        return ConflictResolution.ForceWrite;
            //    });

            localDb = localDb.Refresh();

            localUser = await localDb.Users.Include(_ => _.Posts).FirstOrDefaultAsync(_ => _.Email == "*****@*****.**");

            Assert.AreEqual(3, localUser.Posts.Count);
            Assert.AreEqual("Updated remote for test.", localUser.Posts.First(p => p.Id == postToRemove.Id).Content);

            #endregion
        }
Beispiel #28
0
 private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider)
 {
     return provider.GetAllSyncTargets().Select(i => new SyncTarget
     {
         Name = i.Name,
         Id = GetSyncTargetId(provider, i)
     });
 }
Beispiel #29
0
        private async Task TestSyncAgentWithDataRetention(
            BlogDbContext localDb,
            ISyncProvider localSyncProvider,
            BlogDbContext remoteDb,
            ISyncProvider remoteSyncProvider)
        {
            //setup change tracking
            await remoteSyncProvider.ApplyProvisionAsync();

            //create remote data
            User remoteUser;

            remoteDb.Users.Add(remoteUser = new User()
            {
                Email = "*****@*****.**", Name = "User created before sync", Created = DateTime.Now
            });

            for (int i = 1; i <= 10; i++)
            {
                remoteUser.Posts.Add(new Post()
                {
                    Content = $"Content of Post {i}",
                    Title   = $"Post {i}",
                    Claps   = 1,
                    Stars   = 10
                });
            }

            await remoteDb.SaveChangesAsync();


            //set data retention -> remove first records in the change tracking table
            var remoteSyncVersion = await remoteSyncProvider.GetSyncVersionAsync();

            remoteSyncVersion.Minimum.ShouldBe(1);
            remoteSyncVersion.Current.ShouldBe(11);//1 users + 10 posts

            remoteSyncVersion = await remoteSyncProvider.ApplyRetentionPolicyAsync(4);

            remoteSyncVersion.Minimum.ShouldBe(4);
            remoteSyncVersion.Current.ShouldBe(11);// 11 - 4 = 7 posts

            //local provider is still not synched
            var localSyncVersion = await localSyncProvider.GetSyncVersionAsync();

            localSyncVersion.Minimum.ShouldBe(0);
            localSyncVersion.Current.ShouldBe(0);

            //now let's sync
            var syncAgent = new SyncAgent(localSyncProvider, remoteSyncProvider);
            await syncAgent.SynchronizeAsync();

            localSyncVersion = await localSyncProvider.GetSyncVersionAsync();

            localSyncVersion.Minimum.ShouldBe(0);
            localSyncVersion.Current.ShouldBe(0);

            (await localDb.Users.ToListAsync()).Count.ShouldBe(1);
            (await localDb.Posts.ToListAsync()).Count.ShouldBe(10);

            //now add a new post on server, one on local db than sync
            remoteDb   = remoteDb.Refresh();
            remoteUser = await remoteDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            remoteUser.Posts.Add(new Post()
            {
                Content = $"Another post on server",
                Title   = $"New post on server",
                Claps   = 1,
                Stars   = 10
            });

            await remoteDb.SaveChangesAsync();

            var localUser = await localDb.Users.FirstAsync(_ => _.Email == "*****@*****.**");

            localUser.Posts.Add(new Post()
            {
                Content = $"A post from client",
                Title   = $"New post on client",
                Claps   = 1,
                Stars   = 10
            });

            await localDb.SaveChangesAsync();

            await syncAgent.SynchronizeAsync();

            remoteDb = remoteDb.Refresh();
            localDb  = localDb.Refresh();

            (await remoteDb.Users.SingleAsync()).Email.ShouldBe("*****@*****.**");
            (await localDb.Users.SingleAsync()).Email.ShouldBe("*****@*****.**");

            (await remoteDb.Posts.ToListAsync()).Count.ShouldBe(12);
            (await localDb.Posts.ToListAsync()).Count.ShouldBe(12);


            remoteSyncVersion = await remoteSyncProvider.ApplyRetentionPolicyAsync(4);

            remoteSyncVersion.Minimum.ShouldBe(4);
            remoteSyncVersion.Current.ShouldBe(13);// +2 posts

            localSyncVersion = await localSyncProvider.GetSyncVersionAsync();

            localSyncVersion.Minimum.ShouldBe(1);
            localSyncVersion.Current.ShouldBe(2); // +2 posts
        }
Beispiel #30
0
        private string GetSyncTargetId(ISyncProvider provider, SyncTarget target)
        {
            var hasUniqueId = provider as IHasUniqueTargetIds;

            if (hasUniqueId != null)
            {
                return target.Id;
            }

            return target.Id;
            //var providerId = GetSyncProviderId(provider);
            //return (providerId + "-" + target.Id).GetMD5().ToString("N");
        }
Beispiel #31
0
 public override IFolderSyncState CreateFolderSyncState(StoreObjectId folderObjectId, ISyncProvider syncProvider)
 {
     return(new SyncCalendarFolderSyncState(folderObjectId, syncProvider, base.IcsSyncState));
 }
Beispiel #32
0
 private string GetSyncProviderId(ISyncProvider provider)
 {
     return(provider.GetType().Name.GetMD5().ToString("N"));
 }
        private Dictionary <StoreObjectId, string> ProcessCommand(Dictionary <string, CommonNode> oldItems, Folder sourceFolder, MailboxSession mailboxSession)
        {
            if (oldItems == null)
            {
                throw new ArgumentNullException("items");
            }
            Dictionary <StoreObjectId, string> dictionary = new Dictionary <StoreObjectId, string>();

            if (oldItems.Count == 0)
            {
                return(dictionary);
            }
            GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, ClientManifestEntry> genericDictionaryData = (GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, ClientManifestEntry>) this.syncState[SyncStateProp.CumulativeClientManifest];

            if (genericDictionaryData != null)
            {
                return(null);
            }
            genericDictionaryData = new GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, ClientManifestEntry>();
            this.syncState[SyncStateProp.CumulativeClientManifest] = genericDictionaryData;
            this.clientManifest        = genericDictionaryData.Data;
            this.clientManifest        = new Dictionary <ISyncItemId, ClientManifestEntry>();
            genericDictionaryData.Data = this.clientManifest;
            GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, FolderSync.ClientStateInformation> genericDictionaryData2 = (GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, FolderSync.ClientStateInformation>) this.syncState[SyncStateProp.ClientState];

            if (genericDictionaryData2 != null)
            {
                return(null);
            }
            genericDictionaryData2 = new GenericDictionaryData <DerivedData <ISyncItemId>, ISyncItemId, FolderSync.ClientStateInformation>();
            this.syncState[SyncStateProp.ClientState] = genericDictionaryData2;
            genericDictionaryData2.Data = new Dictionary <ISyncItemId, FolderSync.ClientStateInformation>();
            MailboxSyncProviderFactory mailboxSyncProviderFactory = new MailboxSyncProviderFactory(mailboxSession, sourceFolder.StoreObjectId);
            ISyncProvider syncProvider = mailboxSyncProviderFactory.CreateSyncProvider(null);
            FolderSync    folderSync   = new FolderSync(syncProvider, this.syncState, ConflictResolutionPolicy.ServerWins, false);

            using (QueryResult queryResult = sourceFolder.ItemQuery(ItemQueryType.None, null, null, ItemSyncUpgrade.queryColumns))
            {
                bool flag = false;
                while (!flag && oldItems.Count > 0)
                {
                    object[][] rows = queryResult.GetRows(10000);
                    flag = (rows.Length == 0);
                    int num = 0;
                    while (num < rows.Length && oldItems.Count > 0)
                    {
                        if (!(rows[num][0] is VersionedId) || !(rows[num][1] is int) || !(rows[num][2] is bool))
                        {
                            throw new ApplicationException("The data returned from the query is unusable!");
                        }
                        VersionedId   versionedId    = (VersionedId)rows[num][0];
                        StoreObjectId objectId       = versionedId.ObjectId;
                        int           changeNumber   = (int)rows[num][1];
                        string        messageClass   = rows[num][3] as string;
                        string        oldIdFromNewId = ItemSyncUpgrade.GetOldIdFromNewId(objectId.ProviderLevelItemId);
                        if (oldIdFromNewId == null)
                        {
                            throw new ApplicationException("The new Id is invalid!");
                        }
                        if (oldItems.ContainsKey(oldIdFromNewId))
                        {
                            CommonNode commonNode = oldItems[oldIdFromNewId];
                            oldItems.Remove(oldIdFromNewId);
                            dictionary.Add(objectId, commonNode.ServerId);
                            ISyncItemId syncItemId = MailboxSyncItemId.CreateForNewItem(objectId);
                            FolderSync.ClientStateInformation clientStateInformation = new FolderSync.ClientStateInformation();
                            clientStateInformation.ClientHasItem    = true;
                            genericDictionaryData2.Data[syncItemId] = clientStateInformation;
                            if (!ItemSyncUpgrade.HasChanged(commonNode.VersionId, versionedId))
                            {
                                bool read;
                                if (commonNode.IsEmail && commonNode.Read != (bool)rows[num][2])
                                {
                                    folderSync.QueueDelayedServerOperation(new ServerManifestEntry(syncItemId)
                                    {
                                        ChangeType = ChangeType.ReadFlagChange
                                    });
                                    read = commonNode.Read;
                                }
                                else
                                {
                                    read = (bool)rows[num][2];
                                }
                                ClientManifestEntry clientManifestEntry = new ClientManifestEntry(syncItemId);
                                clientManifestEntry.Watermark    = MailboxSyncWatermark.CreateForSingleItem();
                                clientManifestEntry.ClientAddId  = "TiSyncStateUpgrade";
                                clientManifestEntry.ChangeType   = ChangeType.Add;
                                clientManifestEntry.MessageClass = messageClass;
                                ((MailboxSyncWatermark)clientManifestEntry.Watermark).UpdateWithChangeNumber(changeNumber, read);
                                this.clientManifest.Add(syncItemId, clientManifestEntry);
                            }
                            else
                            {
                                folderSync.QueueDelayedServerOperation(new ServerManifestEntry(syncItemId)
                                {
                                    ChangeType   = ChangeType.Change,
                                    MessageClass = messageClass
                                });
                            }
                        }
                        num++;
                    }
                }
            }
            if (oldItems.Count > 0)
            {
                foreach (KeyValuePair <string, CommonNode> keyValuePair in oldItems)
                {
                    string        key           = keyValuePair.Key;
                    CommonNode    value         = keyValuePair.Value;
                    byte[]        bytes         = Encoding.Unicode.GetBytes(value.ServerId);
                    StoreObjectId storeObjectId = StoreObjectId.FromProviderSpecificId(bytes, StoreObjectType.Mailbox);
                    dictionary.Add(storeObjectId, value.ServerId);
                    MailboxSyncItemId mailboxSyncItemId = MailboxSyncItemId.CreateForNewItem(storeObjectId);
                    folderSync.QueueDelayedServerOperation(new ServerManifestEntry(mailboxSyncItemId)
                    {
                        ChangeType = ChangeType.Delete
                    });
                    FolderSync.ClientStateInformation clientStateInformation2 = new FolderSync.ClientStateInformation();
                    clientStateInformation2.ClientHasItem          = true;
                    genericDictionaryData2.Data[mailboxSyncItemId] = clientStateInformation2;
                }
            }
            return(dictionary);
        }