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
This commit is contained in:
2026-07-11 12:38:31 +02:00
parent 7e267b427e
commit 8a1a579501
2 changed files with 173 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
using System;
namespace ECMJobRunner.Application.Common.Exceptions
{
/// <summary>
/// Exception thrown when a DEX job operation fails
/// </summary>
public class DEXJobException : Exception
{
/// <summary>
/// Initializes a new instance with an inner exception
/// </summary>
/// <param name="queryName">Name of the query that failed</param>
/// <param name="batchId">Batch ID associated with the operation</param>
/// <param name="sqlQuery">SQL query that was executed (nullable)</param>
/// <param name="innerException">The inner exception that caused the failure</param>
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;
}
/// <summary>
/// Initializes a new instance with a reason message
/// </summary>
/// <param name="queryName">Name of the query that failed</param>
/// <param name="batchId">Batch ID associated with the operation</param>
/// <param name="sqlQuery">SQL query that was executed (nullable)</param>
/// <param name="reason">Reason for the failure</param>
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;
}
/// <summary>
/// Gets the SQL query that failed (if available)
/// </summary>
public string? SqlQuery { get; }
/// <summary>
/// Gets the batch ID associated with the operation
/// </summary>
public string BatchId { get; }
/// <summary>
/// Gets the name of the query that failed
/// </summary>
public string QueryName { get; }
}
}

View File

@@ -0,0 +1,105 @@
using ECMJobRunner.Application.Common.Constants;
using System.Text.RegularExpressions;
namespace ECMJobRunner.Application.Common.Options
{
/// <summary>
/// Configuration options for DEX job execution
/// </summary>
public class DexJobOptions
{
/// <summary>
/// Error handling options for DEX job operations
/// </summary>
public record DexJobErrorHandlingOptions
{
/// <summary>
/// Error handling options for SQL query execution
/// </summary>
public record SqlQueryErrorHandlingOptions
{
/// <summary>
/// Action to take when query execution fails
/// </summary>
public ErrorAction OnExecution { get; set; } = ErrorAction.Stop;
/// <summary>
/// Action to take when query is null or whitespace
/// </summary>
public ErrorAction IfNullOrWhiteSpace { get; set; } = ErrorAction.Ignore;
/// <summary>
/// Action to take when query returns unexpected result
/// </summary>
public ErrorAction OnUnexpectedResult { get; set; } = ErrorAction.Stop;
}
/// <summary>
/// Error handling options for HTTP requests
/// </summary>
public record HttpRequestErrorHandlingOptions
{
/// <summary>
/// Action to take when HTTP request fails
/// </summary>
public ErrorAction OnSending { get; set; } = ErrorAction.Stop;
}
/// <summary>
/// Error handling for main SQL query
/// </summary>
public SqlQueryErrorHandlingOptions MainQuery { get; set; } = new();
/// <summary>
/// Error handling for check SQL query
/// </summary>
public SqlQueryErrorHandlingOptions CheckQuery { get; set; } = new();
/// <summary>
/// Error handling for ReC HTTP request
/// </summary>
public HttpRequestErrorHandlingOptions ReCRequest { get; set; } = new();
}
/// <summary>
/// Error handling configuration
/// </summary>
public DexJobErrorHandlingOptions Error { get; set; } = new();
/// <summary>
/// Placeholder configuration for dynamic value replacement
/// </summary>
public record PlaceHolderOptions
{
/// <summary>
/// Configuration for a single placeholder
/// </summary>
public record PlaceHolder
{
/// <summary>
/// Regex pattern to match the placeholder
/// </summary>
public string Pattern { get; set; } = null!;
/// <summary>
/// Regex options for pattern matching
/// </summary>
public RegexOptions RegexOptions { get; set; } = RegexOptions.IgnoreCase;
}
/// <summary>
/// BatchId placeholder configuration
/// </summary>
public PlaceHolder BatchId { get; set; } = new()
{
Pattern = "#INT#BATCH_ID",
RegexOptions = RegexOptions.IgnoreCase
};
}
/// <summary>
/// Placeholder configuration
/// </summary>
public PlaceHolderOptions Placeholders { get; set; } = new();
}
}