Ensure cleanup tasks are run even on a cancelled / exceptioned import task

This commit is contained in:
Dean Herbert 2024-11-18 16:51:34 +09:00
parent 2afd357901
commit ebc2cc3570
No known key found for this signature in database
2 changed files with 72 additions and 61 deletions

View File

@ -68,18 +68,23 @@ protected bool Download(T model, bool minimiseDownloadSize, TModel? originalMode
{ {
Task.Factory.StartNew(async () => Task.Factory.StartNew(async () =>
{ {
bool importSuccessful; bool importSuccessful = false;
if (originalModel != null) try
importSuccessful = (await importer.ImportAsUpdate(notification, new ImportTask(filename), originalModel).ConfigureAwait(false)) != null; {
else if (originalModel != null)
importSuccessful = (await importer.Import(notification, new[] { new ImportTask(filename) }).ConfigureAwait(false)).Any(); importSuccessful = (await importer.ImportAsUpdate(notification, new ImportTask(filename), originalModel).ConfigureAwait(false)) != null;
else
importSuccessful = (await importer.Import(notification, new[] { new ImportTask(filename) }).ConfigureAwait(false)).Any();
}
finally
{
// for now a failed import will be marked as a failed download for simplicity.
if (!importSuccessful)
DownloadFailed?.Invoke(request);
// for now a failed import will be marked as a failed download for simplicity. CurrentDownloads.Remove(request);
if (!importSuccessful) }
DownloadFailed?.Invoke(request);
CurrentDownloads.Remove(request);
}, TaskCreationOptions.LongRunning); }, TaskCreationOptions.LongRunning);
}; };

View File

@ -117,67 +117,73 @@ public async Task<IEnumerable<Live<TModel>>> Import(ProgressNotification notific
await pauseIfNecessaryAsync(parameters, notification, notification.CancellationToken).ConfigureAwait(false); await pauseIfNecessaryAsync(parameters, notification, notification.CancellationToken).ConfigureAwait(false);
await Parallel.ForEachAsync(tasks, notification.CancellationToken, async (task, cancellation) => try
{ {
cancellation.ThrowIfCancellationRequested(); await Parallel.ForEachAsync(tasks, notification.CancellationToken, async (task, cancellation) =>
try
{ {
await pauseIfNecessaryAsync(parameters, notification, cancellation).ConfigureAwait(false); cancellation.ThrowIfCancellationRequested();
var model = await Import(task, parameters, cancellation).ConfigureAwait(false); try
lock (imported)
{ {
if (model != null) await pauseIfNecessaryAsync(parameters, notification, cancellation).ConfigureAwait(false);
imported.Add(model);
current++;
notification.Text = $"Imported {current} of {tasks.Length} {HumanisedModelName}s"; var model = await Import(task, parameters, cancellation).ConfigureAwait(false);
notification.Progress = (float)current / tasks.Length;
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 (OperationCanceledException)
{
throw;
}
catch (Exception e)
{
Logger.Error(e, $@"Could not import ({task})", LoggingTarget.Database);
}
}).ConfigureAwait(false);
}
finally
{
if (imported.Count == 0)
{
if (notification.CancellationToken.IsCancellationRequested)
{
notification.State = ProgressNotificationState.Cancelled;
}
else
{
notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed! Check logs for more information.";
notification.State = ProgressNotificationState.Cancelled;
} }
} }
catch (OperationCanceledException)
{
throw;
}
catch (Exception e)
{
Logger.Error(e, $@"Could not import ({task})", LoggingTarget.Database);
}
}).ConfigureAwait(false);
if (imported.Count == 0)
{
if (notification.CancellationToken.IsCancellationRequested)
{
notification.State = ProgressNotificationState.Cancelled;
return imported;
}
notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed! Check logs for more information.";
notification.State = ProgressNotificationState.Cancelled;
}
else
{
if (tasks.Length > imported.Count)
notification.CompletionText = $"Imported {imported.Count} of {tasks.Length} {HumanisedModelName}s.";
else if (imported.Count > 1)
notification.CompletionText = $"Imported {imported.Count} {HumanisedModelName}s!";
else else
notification.CompletionText = $"Imported {imported.First().GetDisplayString()}!";
if (imported.Count > 0 && PresentImport != null)
{ {
notification.CompletionText += " Click to view."; if (tasks.Length > imported.Count)
notification.CompletionClickAction = () => notification.CompletionText = $"Imported {imported.Count} of {tasks.Length} {HumanisedModelName}s.";
{ else if (imported.Count > 1)
PresentImport?.Invoke(imported); notification.CompletionText = $"Imported {imported.Count} {HumanisedModelName}s!";
return true; else
}; notification.CompletionText = $"Imported {imported.First().GetDisplayString()}!";
}
notification.State = ProgressNotificationState.Completed; if (imported.Count > 0 && PresentImport != null)
{
notification.CompletionText += " Click to view.";
notification.CompletionClickAction = () =>
{
PresentImport?.Invoke(imported);
return true;
};
}
notification.State = ProgressNotificationState.Completed;
}
} }
return imported; return imported;