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"/>
/// changed values are successfully persisted.
/// </summary>
public static event EventHandler<string> BookUserDefinedItemCommitted;
public static event EventHandler BookUserDefinedItemCommitted;
#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
{
if (books is null || !books.Any())
return 0;
using var context = DbContexts.GetContext();
// Attach() NoTracking entities before SaveChanges()
context.Attach(book.UserDefinedItem).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
foreach (var book in books)
context.Attach(book.UserDefinedItem).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
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
{
SearchEngineCommands.UpdateLiberatedStatus(book);
SearchEngineCommands.UpdateBookTags(book);
BookUserDefinedItemCommitted?.Invoke(null, book.AudibleProductId);
foreach (var book in books)
{
SearchEngineCommands.UpdateLiberatedStatus(book);
SearchEngineCommands.UpdateBookTags(book);
}
}
BookUserDefinedItemCommitted?.Invoke(null, null);
return qtyChanges;
}
catch (Exception ex)
{
Log.Logger.Error(ex, $"Error updating {nameof(book.UserDefinedItem)}");
Log.Logger.Error(ex, $"Error updating {nameof(Book.UserDefinedItem)}");
throw;
}
}

View File

@ -141,9 +141,11 @@ namespace DataLayer
get => _bookStatus;
set
{
if (_bookStatus != value)
{
_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 = displayStatus;
OnItemChanged(nameof(BookStatus));
}
}

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DataLayer;
@ -61,7 +63,7 @@ namespace LibationWinForms.BookLiberation
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));
@ -69,7 +71,7 @@ namespace LibationWinForms.BookLiberation
var logMe = LogMe.RegisterForm(automatedBackupsForm);
var backupBook = CreateBackupBook(logMe);
await new BackupLoop(logMe, backupBook, automatedBackupsForm).RunBackupAsync();
await new BackupLoop(logMe, backupBook, automatedBackupsForm, libraryBooks).RunBackupAsync();
}
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 DialogResult SkipResult => DialogResult.Ignore;
public BackupLoop(LogMe logMe, Processable processable, AutomatedBackupsForm automatedBackupsForm)
: base(logMe, processable, automatedBackupsForm) { }
private List<LibraryBook> libraryBooks { get; }
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()
{
// 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);
if (!keepGoing)