mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-13 06:07:30 -04:00
A license denial left no trace: BookStatus stayed NotLiberated, so every liberate run asked again. Only the GUI's bad-book dialog could mark a title Error, and license denials take their own path and never reach that dialog, so a headless install had no way at all to stop the retries. A cron schedule then re-requested the same refused licenses every run and printed the same warning block for each one, which is both wasted API traffic and the log noise reported in issue #1947. Record the refusal instead, with a wait that doubles per consecutive failure: one day for an eligibility denial (up to 30), six hours for a title Audible has no audio for yet such as an unreleased preorder (up to 7 days), one hour when the denial names GenericError, which the GUI already reads as an outage (up to 12). Nothing is permanent - every kind is attempted again on its own. Only failures attributable to Audible are recorded. A dropped connection, a decrypt error or a full disk keeps being retried on the next run as before. Naming a title, --force, and setting a download status all clear the record: asking for a title explicitly overrides the wait. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
68 lines
2.9 KiB
C#
68 lines
2.9 KiB
C#
using DataLayer.Configurations;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace DataLayer;
|
|
|
|
public class LibationContext : DbContext, INotifyDisposed
|
|
{
|
|
// IMPORTANT: USING DbSet<>
|
|
// ========================
|
|
// these run against the db. linq queries against these MUST be translatable to sql. primatives only. no POCOs or this error occurs:
|
|
// Unable to create a constant value of type 'DataLayer.Contributor'. Only primitive types or enumeration types are supported in this context.
|
|
// to use full object-linq, load and use Local. HOWEVER, Local is only hashed/indexed on PK. All other searches are very slow
|
|
// load full table:
|
|
// List<Contributor> contributors = ...;
|
|
// Contributors.Load();
|
|
// Contributors.Local.Where(a => contributors.Contains(a));
|
|
// load only those in object:
|
|
// // overwrite collection
|
|
// Entry(product).Collection(x => x.Narrators).Load();
|
|
// product.Narrators = narrators;
|
|
public DbSet<LibraryBook> LibraryBooks { get; private set; }
|
|
public DbSet<Book> Books { get; private set; }
|
|
public DbSet<Contributor> Contributors { get; private set; }
|
|
public DbSet<Series> Series { get; private set; }
|
|
public DbSet<Category> Categories { get; private set; }
|
|
public DbSet<CategoryLadder> CategoryLadders { get; private set; }
|
|
public DbSet<DownloadHistory> DownloadHistory { get; private set; }
|
|
public DbSet<DownloadAttemptFailure> DownloadAttemptFailures { get; private set; }
|
|
|
|
public event EventHandler? ObjectDisposed;
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
ObjectDisposed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
public override async ValueTask DisposeAsync()
|
|
{
|
|
await base.DisposeAsync();
|
|
ObjectDisposed?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
// see DesignTimeDbContextFactoryBase for info about ctors and connection strings/OnConfiguring()
|
|
public LibationContext(DbContextOptions options) : base(options) { }
|
|
|
|
// typically only called once per execution; NOT once per instantiation
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
modelBuilder.ApplyConfiguration(new BookConfig());
|
|
modelBuilder.ApplyConfiguration(new ContributorConfig());
|
|
modelBuilder.ApplyConfiguration(new BookContributorConfig());
|
|
modelBuilder.ApplyConfiguration(new LibraryBookConfig());
|
|
modelBuilder.ApplyConfiguration(new SeriesConfig());
|
|
modelBuilder.ApplyConfiguration(new SeriesBookConfig());
|
|
modelBuilder.ApplyConfiguration(new CategoryConfig());
|
|
modelBuilder.ApplyConfiguration(new CategoryLadderConfig());
|
|
modelBuilder.ApplyConfiguration(new BookCategoryConfig());
|
|
modelBuilder.ApplyConfiguration(new DownloadHistoryConfig());
|
|
modelBuilder.ApplyConfiguration(new DownloadAttemptFailureConfig());
|
|
|
|
// views are now supported via "keyless entity types" (instead of "entity types" or the prev "query types"):
|
|
// https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types
|
|
}
|
|
}
|