diff --git a/Generation/Converters/Argumentum.AssetConverter/UtilityExtensions.cs b/Generation/Converters/Argumentum.AssetConverter/UtilityExtensions.cs index 48f04f795..82f0ec85b 100644 --- a/Generation/Converters/Argumentum.AssetConverter/UtilityExtensions.cs +++ b/Generation/Converters/Argumentum.AssetConverter/UtilityExtensions.cs @@ -19,6 +19,9 @@ namespace Argumentum.AssetConverter public static class UtilityExtensions { + // Shared HttpClient (was `new HttpClient()` per call — #29 H6). Thread-safe for concurrent calls; + // avoids socket exhaustion / GC pressure on long runs with repeated downloads. Output-neutral. + private static readonly HttpClient _sharedHttpClient = new HttpClient(); public static void ExportDataTable(this CsvWriter writer, DataTable dt) @@ -214,7 +217,7 @@ public static async Task GetDocumentPayload(this string docPath try { // Download the file from the specified URL - using var client = new HttpClient(); + var client = _sharedHttpClient; var response = await client.GetAsync(urlFile); if (response.IsSuccessStatusCode) diff --git a/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/Cardpen/HarvestManager.cs b/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/Cardpen/HarvestManager.cs index 8eadf3569..1c2a2e524 100644 --- a/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/Cardpen/HarvestManager.cs +++ b/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/Cardpen/HarvestManager.cs @@ -356,7 +356,6 @@ public async Task GenerateHarvestImages(Func> bro Log("Entering GenerateHarvestImages."); var currentHarvest = new CardSetHarvest(); var page = await GetFreePage(browser); - var consoleMessages = new List(); void Page_Console(object sender, IConsoleMessage msg) { @@ -408,7 +407,7 @@ void Page_Console(object sender, IConsoleMessage msg) Log("Diagnostic check passed: #cpOutput iframe is ready."); - var faces = await GenerateImages(page, cardSetDocuments.front, configCardSet.Config.FaceCardSetInfo, consoleMessages); + var faces = await GenerateImages(page, cardSetDocuments.front, configCardSet.Config.FaceCardSetInfo); currentHarvest.Faces = faces; // Issue #190 phase 1: opportunistic overflow detection on Virtues face cards. @@ -434,7 +433,7 @@ void Page_Console(object sender, IConsoleMessage msg) if (cardSetDocuments.back != null) { - var backs = await GenerateImages(page, cardSetDocuments.back, configCardSet.Config.BackCardSetInfo, consoleMessages); + var backs = await GenerateImages(page, cardSetDocuments.back, configCardSet.Config.BackCardSetInfo); currentHarvest.Backs = backs; } } @@ -448,7 +447,7 @@ void Page_Console(object sender, IConsoleMessage msg) } - public async Task GenerateImages(IPage page, CardSetPayload cardSetDocument, CardSetInfo cardSetInfo, List consoleMessages) + public async Task GenerateImages(IPage page, CardSetPayload cardSetDocument, CardSetInfo cardSetInfo) { var toReturn = new CardPenHarvest(); if (cardSetDocument?.CardSetDocument == null) diff --git a/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/PrintAndPlayDocument.cs b/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/PrintAndPlayDocument.cs index 43244876f..76d78fd77 100644 --- a/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/PrintAndPlayDocument.cs +++ b/Generation/Converters/Argumentum.AssetConverter/WebBasedGenerator/PrintAndPlayDocument.cs @@ -16,6 +16,10 @@ public class PrintAndPlayDocument : IDocument private readonly List _frontImagesData; private readonly List _backImagesData; + // Header bytes read once and cached (was File.ReadAllBytes per page in ComposePage — #29 H5). + // Identical bytes, just no re-read; output-neutral. + private readonly Lazy _headerImageData; + private const float InchToCentimetre = 2.54f; private const float InchToPoints = 72; private float MmToPointsFactor = 0.1f / InchToCentimetre * InchToPoints; @@ -25,6 +29,15 @@ public PrintAndPlayDocument(CardSetDocumentConfig docConfig, List frontI _docConfig = docConfig; _frontImagesData = frontImagesData; _backImagesData = backImagesData; + _headerImageData = new Lazy(LoadHeaderImageData); + } + + private byte[] LoadHeaderImageData() + { + if (string.IsNullOrEmpty(_docConfig.Header)) + return null; + var imagePath = Path.Combine(Environment.CurrentDirectory, _docConfig.Header); + return File.Exists(imagePath) ? File.ReadAllBytes(imagePath) : null; } public DocumentMetadata GetMetadata() => new DocumentMetadata() @@ -93,14 +106,9 @@ private void ComposePage(PageDescriptor page, PageSize pageSize, float pageMargi page.PageColor(Colors.White); page.DefaultTextStyle(x => x.FontSize(20)); - if (!string.IsNullOrEmpty(_docConfig.Header)) + if (_headerImageData.Value != null) { - var imagePath = Path.Combine(Environment.CurrentDirectory, _docConfig.Header); - if(File.Exists(imagePath)) - { - var imageData = File.ReadAllBytes(imagePath); - page.Header().AlignCenter().Height(pageSize.Height / 10).Padding(pageSize.Width / 150).Image(imageData, ImageScaling.FitHeight); - } + page.Header().AlignCenter().Height(pageSize.Height / 10).Padding(pageSize.Width / 150).Image(_headerImageData.Value, ImageScaling.FitHeight); } page.Content()