From 8a1a57950129ad8bdd8c072dd4be11c6328e79d7 Mon Sep 17 00:00:00 2001 From: TekH Date: Sat, 11 Jul 2026 12:38:31 +0200 Subject: [PATCH] feat: add DEX job exception handling and configuration Exceptions: - DEXJobException: custom exception with formatted error messages * Includes query name, batch ID, SQL query, and detailed error info * Two constructors: with inner exception or reason message * Comprehensive XML documentation Options: - DexJobOptions: hierarchical configuration for DEX job execution * Error handling per stage (MainQuery, CheckQuery, ReCRequest) * Granular error actions (OnExecution, IfNullOrWhiteSpace, OnUnexpectedResult) * Placeholder configuration with regex pattern support * Default BatchId placeholder: #INT#BATCH_ID (case-insensitive) * Fully documented with XML comments --- .../Common/Exceptions/DEXJobException.cs | 68 ++++++++++++ .../Common/Options/DexJobOptions.cs | 105 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 ECMJobRunner.Application/Common/Exceptions/DEXJobException.cs create mode 100644 ECMJobRunner.Application/Common/Options/DexJobOptions.cs diff --git a/ECMJobRunner.Application/Common/Exceptions/DEXJobException.cs b/ECMJobRunner.Application/Common/Exceptions/DEXJobException.cs new file mode 100644 index 0000000..5cb974f --- /dev/null +++ b/ECMJobRunner.Application/Common/Exceptions/DEXJobException.cs @@ -0,0 +1,68 @@ +using System; + +namespace ECMJobRunner.Application.Common.Exceptions +{ + /// + /// Exception thrown when a DEX job operation fails + /// + public class DEXJobException : Exception + { + /// + /// Initializes a new instance with an inner exception + /// + /// Name of the query that failed + /// Batch ID associated with the operation + /// SQL query that was executed (nullable) + /// The inner exception that caused the failure + public DEXJobException(string queryName, string batchId, string? sqlQuery, Exception innerException) + : base( + $"[SQL Execution Failure] Query '{queryName}' could not be completed for Batch '{batchId}'." + Environment.NewLine + + "─────────────────────────────────────────" + Environment.NewLine + + " Query:" + (sqlQuery is null ? string.Empty : Environment.NewLine + $" {sqlQuery}") + Environment.NewLine + Environment.NewLine + + " Root Cause:" + Environment.NewLine + + $" {innerException?.Message}" + Environment.NewLine + + "─────────────────────────────────────────", + innerException) + { + SqlQuery = sqlQuery; + BatchId = batchId; + QueryName = queryName; + } + + /// + /// Initializes a new instance with a reason message + /// + /// Name of the query that failed + /// Batch ID associated with the operation + /// SQL query that was executed (nullable) + /// Reason for the failure + public DEXJobException(string queryName, string batchId, string? sqlQuery, string reason) + : base( + $"[SQL Execution Failure] Query '{queryName}' could not be completed for Batch '{batchId}'." + Environment.NewLine + + "─────────────────────────────────────────" + Environment.NewLine + + " Query:" + (sqlQuery is null ? string.Empty : Environment.NewLine + $" {sqlQuery}") + Environment.NewLine + Environment.NewLine + + " Reason:" + Environment.NewLine + + $" {reason}" + Environment.NewLine + + "─────────────────────────────────────────") + { + SqlQuery = sqlQuery; + BatchId = batchId; + QueryName = queryName; + } + + /// + /// Gets the SQL query that failed (if available) + /// + public string? SqlQuery { get; } + + /// + /// Gets the batch ID associated with the operation + /// + public string BatchId { get; } + + /// + /// Gets the name of the query that failed + /// + public string QueryName { get; } + } +} diff --git a/ECMJobRunner.Application/Common/Options/DexJobOptions.cs b/ECMJobRunner.Application/Common/Options/DexJobOptions.cs new file mode 100644 index 0000000..988fc65 --- /dev/null +++ b/ECMJobRunner.Application/Common/Options/DexJobOptions.cs @@ -0,0 +1,105 @@ +using ECMJobRunner.Application.Common.Constants; +using System.Text.RegularExpressions; + +namespace ECMJobRunner.Application.Common.Options +{ + /// + /// Configuration options for DEX job execution + /// + public class DexJobOptions + { + /// + /// Error handling options for DEX job operations + /// + public record DexJobErrorHandlingOptions + { + /// + /// Error handling options for SQL query execution + /// + public record SqlQueryErrorHandlingOptions + { + /// + /// Action to take when query execution fails + /// + public ErrorAction OnExecution { get; set; } = ErrorAction.Stop; + + /// + /// Action to take when query is null or whitespace + /// + public ErrorAction IfNullOrWhiteSpace { get; set; } = ErrorAction.Ignore; + + /// + /// Action to take when query returns unexpected result + /// + public ErrorAction OnUnexpectedResult { get; set; } = ErrorAction.Stop; + } + + /// + /// Error handling options for HTTP requests + /// + public record HttpRequestErrorHandlingOptions + { + /// + /// Action to take when HTTP request fails + /// + public ErrorAction OnSending { get; set; } = ErrorAction.Stop; + } + + /// + /// Error handling for main SQL query + /// + public SqlQueryErrorHandlingOptions MainQuery { get; set; } = new(); + + /// + /// Error handling for check SQL query + /// + public SqlQueryErrorHandlingOptions CheckQuery { get; set; } = new(); + + /// + /// Error handling for ReC HTTP request + /// + public HttpRequestErrorHandlingOptions ReCRequest { get; set; } = new(); + } + + /// + /// Error handling configuration + /// + public DexJobErrorHandlingOptions Error { get; set; } = new(); + + /// + /// Placeholder configuration for dynamic value replacement + /// + public record PlaceHolderOptions + { + /// + /// Configuration for a single placeholder + /// + public record PlaceHolder + { + /// + /// Regex pattern to match the placeholder + /// + public string Pattern { get; set; } = null!; + + /// + /// Regex options for pattern matching + /// + public RegexOptions RegexOptions { get; set; } = RegexOptions.IgnoreCase; + } + + /// + /// BatchId placeholder configuration + /// + public PlaceHolder BatchId { get; set; } = new() + { + Pattern = "#INT#BATCH_ID", + RegexOptions = RegexOptions.IgnoreCase + }; + } + + /// + /// Placeholder configuration + /// + public PlaceHolderOptions Placeholders { get; set; } = new(); + } +}