From 61f2e6497279d4fb6bf9fd8dff9c98c9984ca44b Mon Sep 17 00:00:00 2001 From: Brian Bicknell Date: Thu, 5 Mar 2026 20:56:57 -0500 Subject: [PATCH] Updated scanner and table names. --- .../Scanning/Ports/IVoiceWorkUpdater.cs | 2 + .../VoiceWorkLocalizationConfiguration.cs | 2 +- .../VoiceWorkSearchConfiguration.cs | 2 +- ...VoiceWorkSupportedLanguageConfiguration.cs | 2 +- .../Ingestion/VoiceWorkUpdater.cs | 5 ++- .../Fixtures/MariaDbContainerFixture.cs | 4 +- JSMR.Tests/Fixtures/MariaDbFixture.cs | 4 +- JSMR.Worker/JSMR.Worker.csproj | 1 + JSMR.Worker/Program.cs | 2 +- JSMR.Worker/Services/ScanJob.cs | 4 +- JSMR.Worker/Services/ScanRunner.cs | 28 ++++++++++--- JSMR.Worker/UI/CliUi.cs | 40 +++++++++++++++++++ 12 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 JSMR.Worker/UI/CliUi.cs diff --git a/JSMR.Application/Scanning/Ports/IVoiceWorkUpdater.cs b/JSMR.Application/Scanning/Ports/IVoiceWorkUpdater.cs index 349eef8..50863e1 100644 --- a/JSMR.Application/Scanning/Ports/IVoiceWorkUpdater.cs +++ b/JSMR.Application/Scanning/Ports/IVoiceWorkUpdater.cs @@ -1,4 +1,5 @@ using JSMR.Application.Scanning.Contracts; +using JSMR.Domain.Enums; namespace JSMR.Application.Scanning.Ports; @@ -10,6 +11,7 @@ public interface IVoiceWorkUpdater public class VoiceWorkUpsertResult { public int? VoiceWorkId { get; set; } + public VoiceWorkStatus UpdateStatus { get; set; } public ICollection Issues { get; } = []; public VoiceWorkUpsertStatus Status { get; set; } = VoiceWorkUpsertStatus.Unchanged; } diff --git a/JSMR.Infrastructure/Data/Configuration/VoiceWorkLocalizationConfiguration.cs b/JSMR.Infrastructure/Data/Configuration/VoiceWorkLocalizationConfiguration.cs index ddfbbe1..bb3fe97 100644 --- a/JSMR.Infrastructure/Data/Configuration/VoiceWorkLocalizationConfiguration.cs +++ b/JSMR.Infrastructure/Data/Configuration/VoiceWorkLocalizationConfiguration.cs @@ -8,7 +8,7 @@ public sealed class VoiceWorkLocalizationConfiguration : IEntityTypeConfiguratio { public void Configure(EntityTypeBuilder builder) { - builder.ToTable("voice_work_localizations"); + builder.ToTable("VoiceWorkLocalizations"); builder.HasKey(x => x.VoiceWorkLocalizationId); builder.Property(x => x.Language).IsRequired().HasMaxLength(10); diff --git a/JSMR.Infrastructure/Data/Configuration/VoiceWorkSearchConfiguration.cs b/JSMR.Infrastructure/Data/Configuration/VoiceWorkSearchConfiguration.cs index a446656..d1f46c1 100644 --- a/JSMR.Infrastructure/Data/Configuration/VoiceWorkSearchConfiguration.cs +++ b/JSMR.Infrastructure/Data/Configuration/VoiceWorkSearchConfiguration.cs @@ -8,7 +8,7 @@ public sealed class VoiceWorkSearchConfiguration : IEntityTypeConfiguration builder) { - builder.ToTable("VoiceWorkSearches2"); + builder.ToTable("VoiceWorkSearches"); builder.HasKey(x => x.VoiceWorkId); // also the FK builder.Property(x => x.SearchText).IsRequired(); // TEXT/LONGTEXT diff --git a/JSMR.Infrastructure/Data/Configuration/VoiceWorkSupportedLanguageConfiguration.cs b/JSMR.Infrastructure/Data/Configuration/VoiceWorkSupportedLanguageConfiguration.cs index 30a2556..c20b001 100644 --- a/JSMR.Infrastructure/Data/Configuration/VoiceWorkSupportedLanguageConfiguration.cs +++ b/JSMR.Infrastructure/Data/Configuration/VoiceWorkSupportedLanguageConfiguration.cs @@ -8,7 +8,7 @@ public sealed class VoiceWorkSupportedLanguageConfiguration : IEntityTypeConfigu { public void Configure(EntityTypeBuilder builder) { - builder.ToTable("voice_work_supported_languages"); + builder.ToTable("VoiceWorkSupportedLanguages"); builder.HasKey(x => x.VoiceWorkSupportedLanguageId); builder.Property(x => x.Language).IsRequired().HasMaxLength(10); diff --git a/JSMR.Infrastructure/Ingestion/VoiceWorkUpdater.cs b/JSMR.Infrastructure/Ingestion/VoiceWorkUpdater.cs index 327cd82..d551643 100644 --- a/JSMR.Infrastructure/Ingestion/VoiceWorkUpdater.cs +++ b/JSMR.Infrastructure/Ingestion/VoiceWorkUpdater.cs @@ -28,6 +28,9 @@ public class VoiceWorkUpdater(AppDbContext dbContext, ITimeProvider timeProvider } result.Status = Upsert(ingest, upsertContext); + + VoiceWork voiceWork = upsertContext.VoiceWorks[ingest.ProductId]; + result.UpdateStatus = (VoiceWorkStatus)voiceWork.Status; } await dbContext.SaveChangesAsync(cancellationToken); @@ -125,7 +128,7 @@ public class VoiceWorkUpdater(AppDbContext dbContext, ITimeProvider timeProvider if (voiceWork.SalesDate is not null && ingest.SalesDate is null) { - string message = $"Voice work has a sales date of {voiceWork.SalesDate.Value.ToShortDateString()}, but ingest does not"; + string message = $"Voice work has a sales date of {voiceWork.SalesDate.Value:d}, but ingest does not"; result.Issues.Add(new(message, VoiceWorkUpsertIssueSeverity.Error)); } } diff --git a/JSMR.Tests/Fixtures/MariaDbContainerFixture.cs b/JSMR.Tests/Fixtures/MariaDbContainerFixture.cs index 85eb3c8..01df4b7 100644 --- a/JSMR.Tests/Fixtures/MariaDbContainerFixture.cs +++ b/JSMR.Tests/Fixtures/MariaDbContainerFixture.cs @@ -19,8 +19,8 @@ public sealed class MariaDbContainerFixture : IAsyncLifetime public async ValueTask InitializeAsync() { - _container = new MariaDbBuilder() - .WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") + _container = new MariaDbBuilder($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") + //.WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") .WithEnvironment("MARIADB_ROOT_PASSWORD", "rootpw") .WithUsername("root") .WithPassword("rootpw") diff --git a/JSMR.Tests/Fixtures/MariaDbFixture.cs b/JSMR.Tests/Fixtures/MariaDbFixture.cs index f8c1c64..719c9dd 100644 --- a/JSMR.Tests/Fixtures/MariaDbFixture.cs +++ b/JSMR.Tests/Fixtures/MariaDbFixture.cs @@ -17,8 +17,8 @@ public class MariaDbFixture : IAsyncLifetime public async ValueTask InitializeAsync() { - MariaDbContainer = new MariaDbBuilder() - .WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") + MariaDbContainer = new MariaDbBuilder($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") + //.WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") .Build(); await MariaDbContainer.StartAsync(); diff --git a/JSMR.Worker/JSMR.Worker.csproj b/JSMR.Worker/JSMR.Worker.csproj index 6774aff..3392897 100644 --- a/JSMR.Worker/JSMR.Worker.csproj +++ b/JSMR.Worker/JSMR.Worker.csproj @@ -29,6 +29,7 @@ + diff --git a/JSMR.Worker/Program.cs b/JSMR.Worker/Program.cs index dd04d2f..bc8bc26 100644 --- a/JSMR.Worker/Program.cs +++ b/JSMR.Worker/Program.cs @@ -97,7 +97,7 @@ scan.SetAction(async (parseResult, cancellationToken) => ScanOptions options = new() { - Locale = parseResult.GetValue(localeOption), + Locale = parseResult.GetValue(localeOption) ?? default!, StartPage = parseResult.GetValue(startOption), EndPage = parseResult.GetValue(endOption), PageSize = parseResult.GetValue(sizeOption), diff --git a/JSMR.Worker/Services/ScanJob.cs b/JSMR.Worker/Services/ScanJob.cs index 14391e5..149baef 100644 --- a/JSMR.Worker/Services/ScanJob.cs +++ b/JSMR.Worker/Services/ScanJob.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Options; namespace JSMR.Worker.Services; -public sealed class ScanJob(ILogger log, IOptions options, ScanVoiceWorksHandler scanVoiceWorksHandler) +public sealed class ScanJob(ILogger log, IOptions options, ScanVoiceWorksHandler handler) { private readonly ScanOptions _options = options.Value; @@ -21,7 +21,7 @@ public sealed class ScanJob(ILogger log, IOptions options, Locale: Enum.Parse(_options.Locale, true) ); - await scanVoiceWorksHandler.HandleAsync(request, cancellationToken); + await handler.HandleAsync(request, cancellationToken); log.LogInformation("Scan completed."); } diff --git a/JSMR.Worker/Services/ScanRunner.cs b/JSMR.Worker/Services/ScanRunner.cs index 4ae312e..a335626 100644 --- a/JSMR.Worker/Services/ScanRunner.cs +++ b/JSMR.Worker/Services/ScanRunner.cs @@ -1,10 +1,13 @@ using JSMR.Application.Enums; using JSMR.Application.Scanning; using JSMR.Application.Scanning.Ports; +using JSMR.Domain.Enums; using JSMR.Infrastructure.Common.Time; using JSMR.Worker.Options; +using JSMR.Worker.UI; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Spectre.Console; using System.Globalization; namespace JSMR.Worker.Services; @@ -39,7 +42,17 @@ public sealed class PagedScanRunner( using var scope = serviceProvider.CreateScope(); ScanVoiceWorksHandler handler = scope.ServiceProvider.GetRequiredService(); - log.LogInformation("Scanning page {Page} (size {Size}, locale {Locale})…", currentPage, pageSize, locale); + //log.LogInformation("Scanning page {Page} (size {Size}, locale {Locale})…", currentPage, pageSize, locale); + CliUi.PageHeader(currentPage, end); + + //AnsiConsole.Status() + //.Start($"[grey]Scanning page[/] [bold]{currentPage}[/] [grey]of[/] [bold]{end}[/][grey]...[/]", ctx => + //{ + // // Simulate grinding + // Thread.Sleep(3000); + //}); + + //AnsiConsole.MarkupLine($"[green]✓ Scanning page[/] [bold]{currentPage}[/] [grey]of[/] [bold]{end}[/][grey]... DONE[/]"); ScanVoiceWorksRequest request = new( PageNumber: currentPage, @@ -49,18 +62,21 @@ public sealed class PagedScanRunner( ScanVoiceWorksResponse response = await handler.HandleAsync(request, cancellationToken); - //int newUpcoming = response.Results.Where(x => x.IsNewUpcoming == true).Count(); + int newUpcoming = response.Results.Count(x => x.UpdateStatus == VoiceWorkStatus.NewAndUpcoming); //if (newUpcoming > 0) - // updatedInfo.Add($"{newUpcoming} new upcoming work(s)"); + // AnsiConsole.MarkupLine($" - {newUpcoming} new upcoming work(s)"); - //int newOnSale = result.ScannedVoiceWorks.Where(x => x.IsNewOnSale == true).Count(); + int newRelease = response.Results.Count(x => x.UpdateStatus == VoiceWorkStatus.NewRelease); - //if (newOnSale > 0) - // updatedInfo.Add($"{newOnSale} new work(s) on sale"); + //if (newRelease > 0) + // updatedInfo.Add($"{newRelease} new work(s) on sale"); + + CliUi.PageHighlights(newUpcoming, newRelease); IEnumerable resultsWithIssues = response.Results.Where(x => x.Issues.Count > 0); + // TODO: Later //foreach (VoiceWorkUpsertResult resultWithIssues in resultsWithIssues) //{ // log.LogWarning($"PRoblem with {resultWithIssues.}") diff --git a/JSMR.Worker/UI/CliUi.cs b/JSMR.Worker/UI/CliUi.cs new file mode 100644 index 0000000..d054f10 --- /dev/null +++ b/JSMR.Worker/UI/CliUi.cs @@ -0,0 +1,40 @@ +namespace JSMR.Worker.UI; + +using Spectre.Console; + +public static class CliUi +{ + public static void PageHeader(int page, int? endPage) + { + AnsiConsole.MarkupLine($"[grey]Scanning page[/] [bold]{page}[/] [grey]of[/] [bold]{endPage}[/][grey]...[/]"); + } + + public static void PageHighlights(int newUpcoming, int newRelease) + { + if (newUpcoming == 0 && newRelease == 0) + return; + + // Nice little boxed summary + var grid = new Grid().AddColumn().AddColumn(); + + if (newUpcoming > 0) + grid.AddRow("[yellow]Upcoming[/]", $"[yellow]{newUpcoming}[/]"); + if (newRelease > 0) + grid.AddRow("[green]New releases[/]", $"[green]{newRelease}[/]"); + + var panel = new Panel(grid) + .Header("[bold]Page updates[/]") + .Border(BoxBorder.Rounded) + .Padding(1, 0, 1, 0); + + AnsiConsole.Write(panel); + } + + public static void Warning(string message) => + AnsiConsole.MarkupLine($"[yellow]⚠ {Escape(message)}[/]"); + + public static void Error(string message) => + AnsiConsole.MarkupLine($"[red]✖ {Escape(message)}[/]"); + + private static string Escape(string s) => Markup.Escape(s); +} \ No newline at end of file