internal void ApplyChanges(ApplyChangesParameter parameter, ref ApplyChangesResult result) { if (parameter == null) { throw new NullReferenceException(nameof(parameter)); } result = new ApplyChangesResult(parameter.PayloadAction, parameter.SynchronizationId, parameter.CustomInfo); parameter.Log.Add("Applying Data Type Changes..."); parameter.Log.Add($"SyncTypes Count: {parameter.Changes.Count}"); List <Type> postEventTypes = new List <Type>(); Dictionary <Type, List <object> > dictDeletedIds = new Dictionary <Type, List <object> >(); for (int i = 0; i < parameter.Changes.Count; i++) { JObject typeChanges = parameter.Changes[i].Value <JObject>(); parameter.Log.Add($"Applying Type: {typeChanges["syncType"].Value<string>()}..."); (Type localSyncType, List <object> appliedIds, List <object> deletedIds) = ApplyTypeChanges(parameter.Log, result.Inserts, result.Updates, result.Deletes, result.Conflicts, typeChanges, parameter.SynchronizationId, parameter.CustomInfo, null, null); parameter.Log.Add($"Type: {typeChanges["syncType"].Value<string>()} Applied, Count: {appliedIds.Count}"); result.AppliedIds[localSyncType] = appliedIds; if (deletedIds.Count > 0) { if (!postEventTypes.Contains(localSyncType)) { postEventTypes.Add(localSyncType); } dictDeletedIds[localSyncType] = deletedIds; } } ProcessPostEvents(parameter.Log, postEventTypes, dictDeletedIds, parameter.SynchronizationId, parameter.CustomInfo); }
public static ApplyChangesResult FromPayload(JObject payload) { string synchronizationId = payload[nameof(SynchronizationId)].Value <string>(); Dictionary <string, object> customInfo = payload[nameof(CustomInfo)].ToObject <Dictionary <string, object> >(); PayloadAction payloadAction = (PayloadAction)Enum.Parse(typeof(PayloadAction), payload[nameof(PayloadAction)].Value <string>()); ApplyChangesResult result = new ApplyChangesResult(payloadAction, synchronizationId, customInfo); result.Inserts = payload[nameof(Inserts)].ToObject <List <SyncLog.SyncLogData> >(); result.Updates = payload[nameof(Updates)].ToObject <List <SyncLog.SyncLogData> >(); result.Deletes = payload[nameof(Deletes)].ToObject <List <SyncLog.SyncLogData> >(); result.Conflicts = payload[nameof(Conflicts)].ToObject <List <SyncLog.SyncLogConflict> >(); result.PayloadAppliedIds = payload[nameof(PayloadAppliedIds)].ToObject <Dictionary <string, List <object> > >(); return(result); }
/// <summary> /// Process pending changes - download thumbnails and update destination with batch document operations. /// </summary> private async Task <ApplyChangesResult> ApplyPendingChanges( IDocumentStorageProvider storage, IClient dropbox, ICollection <PendingChange> pendingChanges, Func <Task> batchProgressAction) { var result = new ApplyChangesResult(); // filter changes according to specified options var filteredChanges = pendingChanges .Where(c => c.Change == DocumentAction.Delete || !_options.WithThumbnailsOnly || c.Meta.thumb_exists || _options.IncludeSharedFolders || String.IsNullOrEmpty(c.Meta.parent_shared_folder_id) ); var itemsProcessed = 0; // split accumulated changes to smaller batches to enable progress reporting and status checks foreach (var batch in filteredChanges.Chunkify(_options.ItemsPerBatch)) { Debug.WriteLine("Processing next batch of changes [{0} / {1}]", itemsProcessed, pendingChanges.Count); // these will buffer metadata updates var documentsToDelete = new List <Document>(); var documentsToUpdate = new List <Document>(); var documentsToAdd = new List <Document>(); // create a list for thumbnail download tasks var thumbsToDownload = new List <PendingChange>(); // sort through updates and adds foreach (var change in batch) { if (change.Change != DocumentAction.Delete && _options.DownloadThumbnails && change.Meta.thumb_exists) { thumbsToDownload.Add(change); } else { var document = change.ToDocument(); switch (change.Change) { case DocumentAction.Add: documentsToAdd.Add(document); break; case DocumentAction.Update: documentsToUpdate.Add(document); break; case DocumentAction.Delete: document.FilePath = change.DeletedFilePath; documentsToDelete.Add(document); break; } } } var downloadCount = await DownloadThumbnails(dropbox, thumbsToDownload, documentsToAdd, documentsToUpdate); result.Skipped += thumbsToDownload.Count - downloadCount; // now flush accumulated changes if (documentsToDelete.Count > 0) { Debug.WriteLine("Deleting documents [{0}]", documentsToDelete.Count); result.Deleted += await storage.DeleteAsync(documentsToDelete); } if (documentsToAdd.Count > 0) { Debug.WriteLine("Adding documents [{0}]", documentsToUpdate.Count + documentsToAdd.Count); result.Added += await storage.AddAsync(documentsToAdd); } if (documentsToUpdate.Count > 0) { Debug.WriteLine("Updating documents [{0}]", documentsToUpdate.Count + documentsToAdd.Count); result.Updated += await storage.UpdateAsync(documentsToUpdate); } if (batchProgressAction != null) { await batchProgressAction(); } itemsProcessed += _options.ItemsPerBatch; } return(result); }