public async Task Sync(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, IProgress <double> progress, CancellationToken cancellationToken) { var serverId = _appHost.SystemId; var serverName = _appHost.FriendlyName; await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(3); var innerProgress = new ActionableProgress <double>(); innerProgress.RegisterAction(pct => { var totalProgress = pct * .97; totalProgress += 1; progress.Report(totalProgress); }); await GetNewMedia(provider, dataProvider, target, serverId, serverName, innerProgress, cancellationToken); // Do the data sync twice so the server knows what was removed from the device await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(100); }
private async Task SyncData(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, SyncTarget target, CancellationToken cancellationToken) { var localIds = await dataProvider.GetServerItemIds(target, serverId).ConfigureAwait(false); var result = await _syncManager.SyncData(new SyncDataRequest { TargetId = target.Id, LocalItemIds = localIds }).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); foreach (var itemIdToRemove in result.ItemIdsToRemove) { try { await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove); } } }
public async Task Sync(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken) { var serverId = _appHost.SystemId; var serverName = _appHost.FriendlyName; await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(3); var innerProgress = new ActionableProgress<double>(); innerProgress.RegisterAction(pct => { var totalProgress = pct * .97; totalProgress += 1; progress.Report(totalProgress); }); await GetNewMedia(provider, dataProvider, target, serverId, serverName, innerProgress, cancellationToken); // Do the data sync twice so the server knows what was removed from the device await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(100); }
private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, string syncJobItemId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId); foreach (var localItem in localItems) { var files = localItem.AdditionalFiles.ToList(); foreach (var file in files) { _logger.Debug("Removing {0} from {1}.", file, target.Name); await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false); } _logger.Debug("Removing {0} from {1}.", localItem.FileId, target.Name); await provider.DeleteFile(localItem.FileId, target, cancellationToken).ConfigureAwait(false); await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); } }
private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, string syncJobItemId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId); foreach (var localItem in localItems) { var files = localItem.AdditionalFiles.ToList(); // TODO: Remove this. Have to check it for now since this is a new property if (!string.IsNullOrWhiteSpace(localItem.FileId)) { files.Insert(0, localItem.FileId); } foreach (var file in files) { _logger.Debug("Removing {0} from {1}.", file, target.Name); await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false); } await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); } }
private async Task GetNewMedia(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, string serverId, string serverName, IProgress <double> progress, CancellationToken cancellationToken) { var jobItems = await _syncManager.GetReadySyncItems(target.Id).ConfigureAwait(false); var numComplete = 0; double startingPercent = 0; double percentPerItem = 1; if (jobItems.Count > 0) { percentPerItem /= jobItems.Count; } foreach (var jobItem in jobItems) { cancellationToken.ThrowIfCancellationRequested(); var currentPercent = startingPercent; var innerProgress = new ActionableProgress <double>(); innerProgress.RegisterAction(pct => { var totalProgress = pct * percentPerItem; totalProgress += currentPercent; progress.Report(totalProgress); }); try { await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error syncing item", ex); } numComplete++; startingPercent = numComplete; startingPercent /= jobItems.Count; startingPercent *= 100; progress.Report(startingPercent); } }
private async Task SyncData(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false); var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false); var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList(); var jobItemIds = new List <string>(); foreach (var localItem in localItems) { // TODO: Remove this after a while if (string.IsNullOrWhiteSpace(localItem.FileId)) { jobItemIds.Add(localItem.SyncJobItemId); } else if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase)) { jobItemIds.Add(localItem.SyncJobItemId); } } var result = await _syncManager.SyncData(new SyncDataRequest { TargetId = target.Id, SyncJobItemIds = jobItemIds }).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); foreach (var itemIdToRemove in result.ItemIdsToRemove) { try { await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove); } } }
private async Task SyncData(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false); var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false); var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList(); var jobItemIds = new List<string>(); foreach (var localItem in localItems) { // TODO: Remove this after a while if (string.IsNullOrWhiteSpace(localItem.FileId)) { jobItemIds.Add(localItem.SyncJobItemId); } else if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase)) { jobItemIds.Add(localItem.SyncJobItemId); } } var result = await _syncManager.SyncData(new SyncDataRequest { TargetId = target.Id, SyncJobItemIds = jobItemIds }).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); foreach (var itemIdToRemove in result.ItemIdsToRemove) { try { await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove); } } }
private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, string itemId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetCachedItems(target, serverId, itemId); foreach (var localItem in localItems) { var files = await GetFiles(provider, localItem, target, cancellationToken); foreach (var file in files) { await provider.DeleteFile(file.Path, target, cancellationToken).ConfigureAwait(false); } await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); } }
private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken) { var failedSubtitles = new List <MediaStream>(); var requiresSave = false; foreach (var mediaStream in mediaSource.MediaStreams .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal) .ToList()) { try { var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target); var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress <double>(), cancellationToken).ConfigureAwait(false); // This is the path that will be used when talking to the provider mediaStream.ExternalId = sendFileResult.Id; // Keep track of all additional files for cleanup later. localItem.AdditionalFiles.Add(sendFileResult.Id); // This is the public path clients will use mediaStream.Path = sendFileResult.Path; requiresSave = true; } catch (Exception ex) { _logger.ErrorException("Error sending subtitle stream", ex); failedSubtitles.Add(mediaStream); } } if (failedSubtitles.Count > 0) { mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList(); requiresSave = true; } if (requiresSave) { await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); } }
private async Task GetItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, string serverId, string serverName, SyncedItem jobItem, IProgress <double> progress, CancellationToken cancellationToken) { var libraryItem = jobItem.Item; var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId); var internalSyncJob = _syncManager.GetJob(jobItem.SyncJobId); var localItem = CreateLocalItem(provider, jobItem, internalSyncJob, target, libraryItem, serverId, serverName, jobItem.OriginalFileName); await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id); var transferSuccess = false; Exception transferException = null; var options = _config.GetSyncOptions(); try { var fileTransferProgress = new ActionableProgress <double>(); fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false); if (localItem.Item.MediaSources != null) { var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); if (mediaSource != null) { mediaSource.Path = sendFileResult.Path; mediaSource.Protocol = sendFileResult.Protocol; mediaSource.RequiredHttpHeaders = sendFileResult.RequiredHttpHeaders; mediaSource.SupportsTranscoding = false; } } localItem.FileId = sendFileResult.Id; // Create db record await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); if (localItem.Item.MediaSources != null) { var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); if (mediaSource != null) { await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false); } } progress.Report(92); transferSuccess = true; progress.Report(99); } catch (Exception ex) { _logger.ErrorException("Error transferring sync job file", ex); transferException = ex; } if (transferSuccess) { await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false); } else { await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false); throw transferException; } }
private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, string syncJobItemId, SyncTarget target, CancellationToken cancellationToken) { var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId); foreach (var localItem in localItems) { var files = localItem.AdditionalFiles.ToList(); foreach (var file in files) { _logger.Debug("Removing {0} from {1}.", file, target.Name); await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false); } await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); } }
private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken) { var failedSubtitles = new List<MediaStream>(); var requiresSave = false; foreach (var mediaStream in mediaSource.MediaStreams .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal) .ToList()) { try { var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target); var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress<double>(), cancellationToken).ConfigureAwait(false); // This is the path that will be used when talking to the provider mediaStream.ExternalId = sendFileResult.Id; // Keep track of all additional files for cleanup later. localItem.AdditionalFiles.Add(sendFileResult.Id); // This is the public path clients will use mediaStream.Path = sendFileResult.Path; requiresSave = true; } catch (Exception ex) { _logger.ErrorException("Error sending subtitle stream", ex); failedSubtitles.Add(mediaStream); } } if (failedSubtitles.Count > 0) { mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList(); requiresSave = true; } if (requiresSave) { await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); } }
private async Task GetItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, string serverId, string serverName, SyncedItem jobItem, IProgress<double> progress, CancellationToken cancellationToken) { var libraryItem = jobItem.Item; var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId); var internalSyncJob = _syncManager.GetJob(jobItem.SyncJobId); var localItem = CreateLocalItem(provider, jobItem, internalSyncJob, target, libraryItem, serverId, serverName, jobItem.OriginalFileName); await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id); var transferSuccess = false; Exception transferException = null; var options = _config.GetSyncOptions(); try { var fileTransferProgress = new ActionableProgress<double>(); fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false); if (localItem.Item.MediaSources != null) { var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); if (mediaSource != null) { mediaSource.Path = sendFileResult.Path; mediaSource.Protocol = sendFileResult.Protocol; mediaSource.RequiredHttpHeaders = sendFileResult.RequiredHttpHeaders; mediaSource.SupportsTranscoding = false; } } localItem.FileId = sendFileResult.Id; // Create db record await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); if (localItem.Item.MediaSources != null) { var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); if (mediaSource != null) { await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false); } } progress.Report(92); transferSuccess = true; progress.Report(99); } catch (Exception ex) { _logger.ErrorException("Error transferring sync job file", ex); transferException = ex; } if (transferSuccess) { await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false); } else { await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false); throw transferException; } }
private async Task GetNewMedia(IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, string serverId, string serverName, IProgress<double> progress, CancellationToken cancellationToken) { var jobItems = await _syncManager.GetReadySyncItems(target.Id).ConfigureAwait(false); var numComplete = 0; double startingPercent = 0; double percentPerItem = 1; if (jobItems.Count > 0) { percentPerItem /= jobItems.Count; } foreach (var jobItem in jobItems) { cancellationToken.ThrowIfCancellationRequested(); var currentPercent = startingPercent; var innerProgress = new ActionableProgress<double>(); innerProgress.RegisterAction(pct => { var totalProgress = pct * percentPerItem; totalProgress += currentPercent; progress.Report(totalProgress); }); try { await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error syncing item", ex); } numComplete++; startingPercent = numComplete; startingPercent /= jobItems.Count; startingPercent *= 100; progress.Report(startingPercent); } }