Exemplo n.º 1
0
        protected async Task <IEnumerable <TModel> > Import(ProgressNotification notification, params string[] paths)
        {
            notification.Progress = 0;
            notification.Text     = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising...";

            int current = 0;

            var imported = new List <TModel>();

            await Task.WhenAll(paths.Select(async path =>
            {
                notification.CancellationToken.ThrowIfCancellationRequested();

                try
                {
                    var model = await Import(path, notification.CancellationToken);

                    lock (imported)
                    {
                        if (model != null)
                        {
                            imported.Add(model);
                        }
                        current++;

                        notification.Text     = $"Imported {current} of {paths.Length} {HumanisedModelName}s";
                        notification.Progress = (float)current / paths.Length;
                    }
                }
                catch (TaskCanceledException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})", LoggingTarget.Database);
                }
            }));

            if (imported.Count == 0)
            {
                notification.Text  = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed!";
                notification.State = ProgressNotificationState.Cancelled;
            }
            else
            {
                notification.CompletionText = imported.Count == 1
                    ? $"Imported {imported.First()}!"
                    : $"Imported {imported.Count} {HumanisedModelName}s!";

                if (imported.Count > 0 && PresentImport != null)
                {
                    notification.CompletionText       += " Click to view.";
                    notification.CompletionClickAction = () =>
                    {
                        PresentImport?.Invoke(imported);
                        return(true);
                    };
                }

                notification.State = ProgressNotificationState.Completed;
            }

            return(imported);
        }
        /// <summary>
        /// Begin a download for the requested <typeparamref name="TModel"/>.
        /// </summary>
        /// <param name="model">The <typeparamref name="TModel"/> to be downloaded.</param>
        /// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
        /// <returns>Whether the download was started.</returns>
        public bool Download(TModel model, bool minimiseDownloadSize = false)
        {
            if (!canDownload(model))
            {
                return(false);
            }

            var request = CreateDownloadRequest(model, minimiseDownloadSize);

            DownloadNotification notification = new DownloadNotification
            {
                Text = $"Downloading {request.Model}",
            };

            request.DownloadProgressed += progress =>
            {
                notification.State    = ProgressNotificationState.Active;
                notification.Progress = progress;
            };

            request.Success += filename =>
            {
                Task.Factory.StartNew(async() =>
                {
                    // This gets scheduled back to the update thread, but we want the import to run in the background.
                    var imported = await Import(notification, filename);

                    // for now a failed import will be marked as a failed download for simplicity.
                    if (!imported.Any())
                    {
                        downloadFailed.Value = new WeakReference <ArchiveDownloadRequest <TModel> >(request);
                    }

                    currentDownloads.Remove(request);
                }, TaskCreationOptions.LongRunning);
            };

            request.Failure += triggerFailure;

            notification.CancelRequested += () =>
            {
                request.Cancel();
                return(true);
            };

            currentDownloads.Add(request);
            PostNotification?.Invoke(notification);

            api.PerformAsync(request);

            downloadBegan.Value = new WeakReference <ArchiveDownloadRequest <TModel> >(request);
            return(true);

            void triggerFailure(Exception error)
            {
                currentDownloads.Remove(request);

                downloadFailed.Value = new WeakReference <ArchiveDownloadRequest <TModel> >(request);

                notification.State = ProgressNotificationState.Cancelled;

                if (!(error is OperationCanceledException))
                {
                    Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!");
                }
            }
        }
Exemplo n.º 3
0
        public async Task <IEnumerable <ILive <TModel> > > Import(ProgressNotification notification, params ImportTask[] tasks)
        {
            if (tasks.Length == 0)
            {
                notification.CompletionText = $"No {HumanisedModelName}s were found to import!";
                notification.State          = ProgressNotificationState.Completed;
                return(Enumerable.Empty <ILive <TModel> >());
            }

            notification.Progress = 0;
            notification.Text     = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising...";

            int current = 0;

            var imported = new List <ILive <TModel> >();

            bool isLowPriorityImport = tasks.Length > low_priority_import_batch_size;

            try
            {
                await Task.WhenAll(tasks.Select(async task =>
                {
                    notification.CancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        var model = await Import(task, isLowPriorityImport, notification.CancellationToken).ConfigureAwait(false);

                        lock (imported)
                        {
                            if (model != null)
                            {
                                imported.Add(model);
                            }
                            current++;

                            notification.Text     = $"Imported {current} of {tasks.Length} {HumanisedModelName}s";
                            notification.Progress = (float)current / tasks.Length;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        Logger.Error(e, $@"Could not import ({task})", LoggingTarget.Database);
                    }
                })).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                if (imported.Count == 0)
                {
                    notification.State = ProgressNotificationState.Cancelled;
                    return(imported);
                }
            }

            if (imported.Count == 0)
            {
                notification.Text  = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed!";
                notification.State = ProgressNotificationState.Cancelled;
            }
            else
            {
                notification.CompletionText = imported.Count == 1
                    ? $"Imported {imported.First().Value.GetDisplayString()}!"
                    : $"Imported {imported.Count} {HumanisedModelName}s!";

                if (imported.Count > 0 && PostImport != null)
                {
                    notification.CompletionText       += " Click to view.";
                    notification.CompletionClickAction = () =>
                    {
                        PostImport?.Invoke(imported);
                        return(true);
                    };
                }

                notification.State = ProgressNotificationState.Completed;
            }

            return(imported);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Begin a download for the requested <see cref="TModel"/>.
        /// </summary>
        /// <param name="model">The <see cref="TModel"/> to be downloaded.</param>
        /// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
        /// <returns>Whether the download was started.</returns>
        public bool Download(TModel model, bool minimiseDownloadSize = false)
        {
            if (!canDownload(model))
            {
                return(false);
            }

            var request = CreateDownloadRequest(model, minimiseDownloadSize);

            DownloadNotification notification = new DownloadNotification
            {
                Text = $"Downloading {request.Model}",
            };

            request.DownloadProgressed += progress =>
            {
                notification.State    = ProgressNotificationState.Active;
                notification.Progress = progress;
            };

            request.Success += filename =>
            {
                Task.Factory.StartNew(async() =>
                {
                    // This gets scheduled back to the update thread, but we want the import to run in the background.
                    await Import(notification, filename);
                    currentDownloads.Remove(request);
                }, TaskCreationOptions.LongRunning);
            };

            request.Failure += error =>
            {
                DownloadFailed?.Invoke(request);

                if (error is OperationCanceledException)
                {
                    return;
                }

                notification.State = ProgressNotificationState.Cancelled;
                Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!");
                currentDownloads.Remove(request);
            };

            notification.CancelRequested += () =>
            {
                request.Cancel();
                currentDownloads.Remove(request);
                notification.State = ProgressNotificationState.Cancelled;
                return(true);
            };

            currentDownloads.Add(request);
            PostNotification?.Invoke(notification);

            Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning);

            DownloadBegan?.Invoke(request);

            return(true);
        }