using System; using System.Linq; using System.Threading.Tasks; using ApplicationServices; using DataLayer; using Dinah.Core.ErrorHandling; namespace FileLiberator { public static class IProcessableExt { // // DO NOT USE ConfigureAwait(false) WITH ProcessAsync() unless ensuring ProcessAsync() implementation is cross-thread compatible // ProcessAsync() often does a lot with forms in the UI context // /// Process the first valid product. Create default context /// Returns either the status handler from the process, or null if all books have been processed public static async Task ProcessFirstValidAsync(this IProcessable processable) { var libraryBook = processable.getNextValidBook(); if (libraryBook == null) return null; return await processBookAsync(processable, libraryBook); } /// Process the first valid product. Create default context /// Returns either the status handler from the process, or null if all books have been processed public static async Task ProcessSingleAsync(this IProcessable processable, string productId) { using var context = DbContexts.GetContext(); var libraryBook = context .Library .GetLibrary() .SingleOrDefault(lb => lb.Book.AudibleProductId == productId); if (libraryBook == null) return null; if (!processable.Validate(libraryBook)) return new StatusHandler { "Validation failed" }; return await processBookAsync(processable, libraryBook); } private static async Task processBookAsync(IProcessable processable, LibraryBook libraryBook) { Serilog.Log.Information("Begin " + nameof(processBookAsync) + " {@DebugInfo}", new { libraryBook.Book.Title, libraryBook.Book.AudibleProductId, libraryBook.Book.Locale, libraryBook.Account }); // this should never happen. check anyway. ProcessFirstValidAsync returning null is the signal that we're done. we can't let another IProcessable accidentally send this command var status = await processable.ProcessAsync(libraryBook); if (status == null) throw new Exception("Processable should never return a null status"); return status; } private static LibraryBook getNextValidBook(this IProcessable processable) { var libraryBooks = DbContexts.GetContext().GetLibrary_Flat_NoTracking(); foreach (var libraryBook in libraryBooks) if (processable.Validate(libraryBook)) return libraryBook; return null; } public static async Task TryProcessAsync(this IProcessable processable, LibraryBook libraryBook) => processable.Validate(libraryBook) ? await processable.ProcessAsync(libraryBook) : new StatusHandler(); } }