Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor PDF generation with ReportSheetCache #190

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions League/Caching/ReportSheetCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ public ReportSheetCache(ITenantContext tenantContext, IConfiguration configurati
_pathToChromium = Path.Combine(webHostEnvironment.ContentRootPath, configuration["Chromium:ExecutablePath"] ?? string.Empty);
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<ReportSheetCache>();
UsePuppeteer = false;
}

/// <summary>
/// Gets or sets a value indicating whether to use Puppeteer for generating the report sheet,
/// instead of Chromium command line.
/// </summary>
public bool UsePuppeteer { get; set; } = false;
public bool UsePuppeteer { get; set; }

private void EnsureCacheFolder()
{
Expand Down Expand Up @@ -108,7 +109,7 @@ private static bool IsOutdated(string cacheFile, DateTime dataModifiedOn)
// Temporary file with HTML content - extension must be ".html"!
var htmlUri = await CreateHtmlFile(html, tempFolder, cancellationToken);

var pdfFile = await CreateReportSheetPdfChromium(tempFolder, htmlUri);
var pdfFile = await CreateReportSheetPdfChromium(tempFolder, htmlUri, cancellationToken);

var cacheFile = MovePdfToCache(pdfFile, matchId);

Expand Down Expand Up @@ -154,7 +155,7 @@ private string GetPathToCacheFile(long matchId)
{ "--no-sandbox", "--disable-gpu", "--disable-extensions", "--use-cmd-decoder=passthrough" },
ExecutablePath = _pathToChromium,
Timeout = 5000,
ProtocolTimeout = 10000 // default is 180,000
ProtocolTimeout = 10000 // default is 180,000 - used for page.PdfDataAsync
};
// Use Puppeteer as a wrapper for the browser, which can generate PDF from HTML
// Start command line arguments set by Puppeteer v20:
Expand All @@ -168,7 +169,6 @@ private string GetPathToCacheFile(long matchId)
var fullPath = GetPathToCacheFile(matchId);
try
{
// page.PdfDataAsync times out after 180,000ms (3 minutes)
var bytes = await page.PdfDataAsync(new PuppeteerSharp.PdfOptions
{ Scale = 1.0M, Format = PuppeteerSharp.Media.PaperFormat.A4 }).ConfigureAwait(false);

Expand All @@ -183,9 +183,10 @@ private string GetPathToCacheFile(long matchId)
return fullPath;
}

private async Task<string> CreateReportSheetPdfChromium(string tempFolder, string htmlUri)
private async Task<string> CreateReportSheetPdfChromium(string tempFolder, string htmlUri, CancellationToken cancellationToken)
{
// Temporary file for the PDF stream form Chromium
// Temporary file for the PDF stream from Chromium
// Note: non-existing file is handled in MovePdfToCache
var pdfFile = Path.Combine(tempFolder, Path.GetRandomFileName() + ".pdf");

// Run Chromium
Expand All @@ -196,25 +197,21 @@ private async Task<string> CreateReportSheetPdfChromium(string tempFolder, strin
{ CreateNoWindow = true, UseShellExecute = false };
var proc = System.Diagnostics.Process.Start(startInfo);

if (proc is null)
if (proc == null)
{
_logger.LogError("Process '{PathToChromium}' could not be started.", _pathToChromium);
return pdfFile;
}

const int timeout = 8000;
var timePassed = 0;
while (proc is { HasExited: false })
{
timePassed += 100;
await Task.Delay(100, default);
if (timePassed < timeout) continue;
var timeout = TimeSpan.FromMilliseconds(5000);
var processTask = proc.WaitForExitAsync(cancellationToken);

proc.Kill(true);
throw new OperationCanceledException($"Chromium timed out after {timeout}ms.");
}
await Task.WhenAny(processTask, Task.Delay(timeout, cancellationToken));

if (processTask.IsCompleted) return pdfFile;

// non-existing file is handled in MovePdfToCache
return pdfFile;
proc.Kill(true);
throw new OperationCanceledException($"Chromium timed out after {timeout.TotalMilliseconds}ms.");
}

private static async Task<string> CreateHtmlFile(string html, string tempFolder, CancellationToken cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Match.cs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ private async Task<EnterResultViewModel> GetEnterResultViewModel(MatchEntity mat
public async Task<IActionResult> ReportSheet(long id, [FromServices] ReportSheetCache cache, CancellationToken cancellationToken)
{
MatchReportSheetRow? model = null;
cache.UsePuppeteer = true;
cache.UsePuppeteer = false;

try
{
Expand Down