Improve SetBeckupCounts

Change Avalonia's Task-based approach to WinForms' BackgroundWorker approach.
- Reduce number of calls to GetLibrary by adding the Library to the LibraryStats record.
This commit is contained in:
Michael Bucari-Tovo
2025-11-25 14:59:48 -07:00
parent ffbb3c3516
commit b577ef7187
5 changed files with 65 additions and 25 deletions

View File

@@ -586,7 +586,7 @@ namespace ApplicationServices
// below are queries, not commands. maybe I should make a LibraryQueries. except there's already one of those...
public record LibraryStats(int booksFullyBackedUp, int booksDownloadedOnly, int booksNoProgress, int booksError, int booksUnavailable, int pdfsDownloaded, int pdfsNotDownloaded, int pdfsUnavailable)
public record LibraryStats(int booksFullyBackedUp, int booksDownloadedOnly, int booksNoProgress, int booksError, int booksUnavailable, int pdfsDownloaded, int pdfsNotDownloaded, int pdfsUnavailable, IEnumerable<LibraryBook> LibraryBooks)
{
public int PendingBooks => booksNoProgress + booksDownloadedOnly;
public bool HasPendingBooks => PendingBooks > 0;
@@ -655,7 +655,7 @@ namespace ApplicationServices
Log.Logger.Information("PDF counts. {@DebugInfo}", new { total = pdfResults.Count, pdfsDownloaded, pdfsNotDownloaded, pdfsUnavailable });
return new(booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError, booksUnavailable, pdfsDownloaded, pdfsNotDownloaded, pdfsUnavailable);
return new(booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError, booksUnavailable, pdfsDownloaded, pdfsNotDownloaded, pdfsUnavailable, libraryBooks);
}
}
}

View File

@@ -1,5 +1,4 @@
using ApplicationServices;
using Avalonia.Threading;
using DataLayer;
using LibationFileManager;
using ReactiveUI;
@@ -11,7 +10,7 @@ namespace LibationAvalonia.ViewModels
{
partial class MainVM
{
private Task<LibraryCommands.LibraryStats>? updateCountsTask;
private System.ComponentModel.BackgroundWorker updateCountsBw = new();
/// <summary> The "Begin Book and PDF Backup" menu item header text </summary>
public string BookBackupsToolStripText { get; private set; } = "Begin Book and PDF Backups: 0";
@@ -46,20 +45,40 @@ namespace LibationAvalonia.ViewModels
//Pass null to the setup count to get the whole library.
LibraryCommands.BookUserDefinedItemCommitted += async (_, _)
=> await SetBackupCountsAsync(null);
updateCountsBw.DoWork += UpdateCountsBw_DoWork;
updateCountsBw.RunWorkerCompleted += UpdateCountsBw_Completed; ;
}
private bool runBackupCountsAgain;
public async Task SetBackupCountsAsync(IEnumerable<LibraryBook>? libraryBooks)
{
if (updateCountsTask?.IsCompleted ?? true)
{
updateCountsTask = Task.Run(() => LibraryCommands.GetCounts(libraryBooks));
var stats = await updateCountsTask;
await Dispatcher.UIThread.InvokeAsync(() => LibraryStats = stats);
runBackupCountsAgain = true;
if (Configuration.Instance.AutoDownloadEpisodes
&& stats.PendingBooks + stats.pdfsNotDownloaded > 0)
await Dispatcher.UIThread.InvokeAsync(BackupAllBooks);
if (!updateCountsBw.IsBusy)
updateCountsBw.RunWorkerAsync(libraryBooks);
}
private void UpdateCountsBw_DoWork(object? sender, System.ComponentModel.DoWorkEventArgs e)
{
while (runBackupCountsAgain)
{
runBackupCountsAgain = false;
e.Result = LibraryCommands.GetCounts(e.Argument as IEnumerable<LibraryBook>);
}
}
private void UpdateCountsBw_Completed(object? sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Result is not LibraryCommands.LibraryStats stats)
return;
LibraryStats = stats;
if (Configuration.Instance.AutoDownloadEpisodes
&& stats.PendingBooks + stats.pdfsNotDownloaded > 0)
BackupAllBooks(stats.LibraryBooks);
}
}
}

View File

@@ -7,6 +7,7 @@ using DataLayer;
using LibationUiBase.Forms;
using LibationUiBase;
using System.Collections.Generic;
using Avalonia.Threading;
#nullable enable
namespace LibationAvalonia.ViewModels
@@ -15,14 +16,24 @@ namespace LibationAvalonia.ViewModels
{
public void Configure_Liberate() { }
/// <summary> This gets called by the "Begin Book and PDF Backups" menu item. </summary>
public async Task BackupAllBooks()
{
var books = await Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking());
BackupAllBooks(books);
}
private void BackupAllBooks(IEnumerable<LibraryBook> books)
{
try
{
var unliberated = await Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking().UnLiberated().ToArray());
var unliberated = books.UnLiberated().ToArray();
if (ProcessQueue.QueueDownloadDecrypt(unliberated))
setQueueCollapseState(false);
Dispatcher.UIThread.Invoke(() =>
{
if (ProcessQueue.QueueDownloadDecrypt(unliberated))
setQueueCollapseState(false);
});
}
catch (Exception ex)
{
@@ -30,9 +41,11 @@ namespace LibationAvalonia.ViewModels
}
}
/// <summary> This gets called by the "Begin PDF Only Backups" menu item. </summary>
public async Task BackupAllPdfs()
{
if (ProcessQueue.QueueDownloadPdf(await Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking())))
var books = await Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking());
if (ProcessQueue.QueueDownloadPdf(books))
setQueueCollapseState(false);
}

View File

@@ -1,6 +1,7 @@
using DataLayer;
using LibationUiBase;
using ApplicationServices;
using DataLayer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -13,12 +14,21 @@ namespace LibationWinForms
//GetLibrary_Flat_NoTracking() may take a long time on a hugh library. so run in new thread
private async void beginBookBackupsToolStripMenuItem_Click(object _ = null, EventArgs __ = null)
{
var library = await Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking());
BackupAllBooks(library);
}
private void BackupAllBooks(IEnumerable<LibraryBook> books)
{
try
{
var unliberated = await Task.Run(() => ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking().UnLiberated().ToArray());
if (processBookQueue1.ViewModel.QueueDownloadDecrypt(unliberated))
SetQueueCollapseState(false);
var unliberated = books.UnLiberated().ToArray();
Invoke(() =>
{
if (processBookQueue1.ViewModel.QueueDownloadDecrypt(unliberated))
SetQueueCollapseState(false);
});
}
catch (Exception ex)
{

View File

@@ -28,13 +28,11 @@ namespace LibationWinForms
// winforms only. this should NOT be allowed in cli
updateCountsBw.RunWorkerCompleted += (object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) =>
{
if (!Configuration.Instance.AutoDownloadEpisodes)
if (!Configuration.Instance.AutoDownloadEpisodes || e.Result is not LibraryCommands.LibraryStats libraryStats)
return;
var libraryStats = e.Result as LibraryCommands.LibraryStats;
if ((libraryStats.PendingBooks + libraryStats.pdfsNotDownloaded) > 0)
Invoke(() => beginBookBackupsToolStripMenuItem_Click(null, System.EventArgs.Empty));
BackupAllBooks(libraryStats.LibraryBooks);
};
}