From f8c586dd3154f49a506d2a58b97dea0a3e682dc0 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 10 Nov 2025 15:01:07 +0100 Subject: [PATCH] feat(FinishEnvelopeJob): add PDF burning with concurrency control - Introduced PDFBurnerParams configuration for concurrency limit. - Added SemaphoreSlim to handle concurrent PDF burning for envelopes. - Updated job to call _mediator.BurnPdf for each envelope with error handling. - Preserved logging of job execution and envelope UUIDs. --- .../Common/Configurations/PDFBurnerParams.cs | 5 +++ .../Pdf/BurnPdfCommand.cs | 4 +- .../Job/FinishEnvelopeJob.cs | 38 ++++++++++++++----- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/EnvelopeGenerator.Application/Common/Configurations/PDFBurnerParams.cs b/EnvelopeGenerator.Application/Common/Configurations/PDFBurnerParams.cs index ab41c0a6..a6e0a455 100644 --- a/EnvelopeGenerator.Application/Common/Configurations/PDFBurnerParams.cs +++ b/EnvelopeGenerator.Application/Common/Configurations/PDFBurnerParams.cs @@ -9,6 +9,11 @@ namespace EnvelopeGenerator.Application.Common.Configurations; /// public class PDFBurnerParams : ITextStyle { + /// + /// + /// + public int ConcurrencyLimit { get; set; } = 5; + /// /// /// diff --git a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs index 38f7fe74..b5dfdcc5 100644 --- a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs +++ b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs @@ -32,7 +32,7 @@ public static class BurnPdfCommandExtensions /// /// /// - public static Task BurnPdf(this ISender sender, int envelopeId, CancellationToken cancel) + public static Task BurnPdf(this ISender sender, int envelopeId, CancellationToken cancel = default) => sender.Send(new BurnPdfCommand(EnvelopeId: envelopeId), cancel); /// @@ -42,7 +42,7 @@ public static class BurnPdfCommandExtensions /// /// /// - public static Task BurnPdf(this ISender sender, string envelopeUuid, CancellationToken cancel) + public static Task BurnPdf(this ISender sender, string envelopeUuid, CancellationToken cancel = default) => sender.Send(new BurnPdfCommand(EnvelopeUuid: envelopeUuid), cancel); } diff --git a/EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs b/EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs index 94e8eb7d..7895fb12 100644 --- a/EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs +++ b/EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs @@ -1,6 +1,7 @@ +using EnvelopeGenerator.Application.Common.Configurations; using EnvelopeGenerator.Application.Envelopes.Queries; +using EnvelopeGenerator.Application.Pdf; using EnvelopeGenerator.Domain.Constants; -using EnvelopeGenerator.Finalizer.Models; using MediatR; using Microsoft.Extensions.Options; using Quartz; @@ -13,10 +14,13 @@ namespace EnvelopeGenerator.Finalizer.Job private readonly IMediator _mediator; - public FinishEnvelopeJob(ILogger logger, IMediator mediator) + private readonly PDFBurnerParams _options; + + public FinishEnvelopeJob(ILogger logger, IMediator mediator, IOptions options) { _logger = logger; _mediator = mediator; + _options = options.Value; } public async Task Execute(IJobExecutionContext context) @@ -29,23 +33,39 @@ namespace EnvelopeGenerator.Finalizer.Job HasDocResult = false }, cancel); - foreach (var envelope in envelopes) + using var semaphore = new SemaphoreSlim(_options.ConcurrencyLimit); + await Task.WhenAll(envelopes.Select(async envelope => { - // add sub-steps - } + await semaphore.WaitAsync(cancel); + try + { + await _mediator.BurnPdf(envelope.Id, cancel); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error burning envelope {EnvelopeId}", envelope.Id); + } + finally + { + semaphore.Release(); + } + })); - if (envelopes.Any()) + var envelopeCount = envelopes.Count(); + if (envelopeCount > 0) + { _logger.LogInformation( "Job '{JobName}' executed at {Timestamp}. {EnvelopeCount} envelope(s) successfully finalized. UUID(s): {EnvelopeUuids}", context.JobDetail.Key.Name, - DateTimeOffset.Now, - envelopes.Count(), + context.FireTimeUtc.ToLocalTime(), + envelopeCount, string.Join(", ", envelopes.Select(e => e.Uuid)) ); + } else _logger.LogInformation("Job '{JobName}' executed successfully at {Timestamp}. No envelopes were finalized.", context.JobDetail.Key.Name, - DateTimeOffset.Now + context.FireTimeUtc.ToLocalTime() ); } }