Set the stage for batch processing

This commit is contained in:
Robert McRackan 2022-05-10 16:18:09 -04:00
parent dd5e162c10
commit c6ce814e1c
3 changed files with 40 additions and 16 deletions

View File

@ -266,30 +266,47 @@ namespace ApplicationServices
/// Occurs when <see cref="UserDefinedItem.Tags"/>, <see cref="UserDefinedItem.BookStatus"/>, or <see cref="UserDefinedItem.PdfStatus"/> /// Occurs when <see cref="UserDefinedItem.Tags"/>, <see cref="UserDefinedItem.BookStatus"/>, or <see cref="UserDefinedItem.PdfStatus"/>
/// changed values are successfully persisted. /// changed values are successfully persisted.
/// </summary> /// </summary>
public static event EventHandler<string> BookUserDefinedItemCommitted; public static event EventHandler BookUserDefinedItemCommitted;
#region Update book details #region Update book details
public static int UpdateUserDefinedItem(Book book) public static int UpdateUserDefinedItem(params Book[] books) => UpdateUserDefinedItem(books.ToList());
public static int UpdateUserDefinedItem(IEnumerable<Book> books)
{ {
try try
{ {
if (books is null || !books.Any())
return 0;
using var context = DbContexts.GetContext(); using var context = DbContexts.GetContext();
// Attach() NoTracking entities before SaveChanges() // Attach() NoTracking entities before SaveChanges()
foreach (var book in books)
context.Attach(book.UserDefinedItem).State = Microsoft.EntityFrameworkCore.EntityState.Modified; context.Attach(book.UserDefinedItem).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
var qtyChanges = context.SaveChanges(); var qtyChanges = context.SaveChanges();
if (qtyChanges > 0) if (qtyChanges == 0)
return 0;
// semi-arbitrary. At some point it's more worth it to do a full re-index than to do one offs.
// I did not benchmark before choosing the number here
if (qtyChanges > 15)
SearchEngineCommands.FullReIndex();
else
{
foreach (var book in books)
{ {
SearchEngineCommands.UpdateLiberatedStatus(book); SearchEngineCommands.UpdateLiberatedStatus(book);
SearchEngineCommands.UpdateBookTags(book); SearchEngineCommands.UpdateBookTags(book);
BookUserDefinedItemCommitted?.Invoke(null, book.AudibleProductId);
} }
}
BookUserDefinedItemCommitted?.Invoke(null, null);
return qtyChanges; return qtyChanges;
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Logger.Error(ex, $"Error updating {nameof(book.UserDefinedItem)}"); Log.Logger.Error(ex, $"Error updating {nameof(Book.UserDefinedItem)}");
throw; throw;
} }
} }

View File

@ -141,9 +141,11 @@ namespace DataLayer
get => _bookStatus; get => _bookStatus;
set set
{ {
if (_bookStatus != value) // PartialDownload is a live/ephemeral status, not a persistent one. Do not store
var displayStatus = value == LiberatedStatus.PartialDownload ? LiberatedStatus.NotLiberated : value;
if (_bookStatus != displayStatus)
{ {
_bookStatus = value; _bookStatus = displayStatus;
OnItemChanged(nameof(BookStatus)); OnItemChanged(nameof(BookStatus));
} }
} }

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using DataLayer; using DataLayer;
@ -61,7 +63,7 @@ namespace LibationWinForms.BookLiberation
await new BackupSingle(logMe, backupBook, libraryBook).RunBackupAsync(); await new BackupSingle(logMe, backupBook, libraryBook).RunBackupAsync();
} }
public static async Task BackupAllBooksAsync() public static async Task BackupAllBooksAsync(List<LibraryBook> libraryBooks = null)
{ {
Serilog.Log.Logger.Information("Begin " + nameof(BackupAllBooksAsync)); Serilog.Log.Logger.Information("Begin " + nameof(BackupAllBooksAsync));
@ -69,7 +71,7 @@ namespace LibationWinForms.BookLiberation
var logMe = LogMe.RegisterForm(automatedBackupsForm); var logMe = LogMe.RegisterForm(automatedBackupsForm);
var backupBook = CreateBackupBook(logMe); var backupBook = CreateBackupBook(logMe);
await new BackupLoop(logMe, backupBook, automatedBackupsForm).RunBackupAsync(); await new BackupLoop(logMe, backupBook, automatedBackupsForm, libraryBooks).RunBackupAsync();
} }
public static async Task ConvertAllBooksAsync() public static async Task ConvertAllBooksAsync()
@ -307,13 +309,16 @@ An error occurred while trying to process this book.
protected override MessageBoxDefaultButton SkipDialogDefaultButton => MessageBoxDefaultButton.Button1; protected override MessageBoxDefaultButton SkipDialogDefaultButton => MessageBoxDefaultButton.Button1;
protected override DialogResult SkipResult => DialogResult.Ignore; protected override DialogResult SkipResult => DialogResult.Ignore;
public BackupLoop(LogMe logMe, Processable processable, AutomatedBackupsForm automatedBackupsForm) private List<LibraryBook> libraryBooks { get; }
: base(logMe, processable, automatedBackupsForm) { }
public BackupLoop(LogMe logMe, Processable processable, AutomatedBackupsForm automatedBackupsForm, List<LibraryBook> libraryBooks = null)
: base(logMe, processable, automatedBackupsForm)
=> this.libraryBooks = libraryBooks ?? ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking();
protected override async Task RunAsync() protected override async Task RunAsync()
{ {
// support for 'skip this time only' requires state. iterators provide this state for free. therefore: use foreach/iterator here // support for 'skip this time only' requires state. iterators provide this state for free. therefore: use foreach/iterator here
foreach (var libraryBook in Processable.GetValidLibraryBooks(ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking())) foreach (var libraryBook in Processable.GetValidLibraryBooks(libraryBooks))
{ {
var keepGoing = await ProcessOneAsync(libraryBook, validate: false); var keepGoing = await ProcessOneAsync(libraryBook, validate: false);
if (!keepGoing) if (!keepGoing)