using System; using System.Collections.Generic; namespace ECMJobRunner.Application.Common.Exceptions { /// /// Base exception class for job execution failures /// Provides a flexible structure for capturing job context and detailed error information /// public class JobException : Exception { /// /// Initializes a new instance of JobException with detailed context information /// /// Name of the job that failed (e.g., "SQL Main Query", "ReC Request") /// Name of the process/stage being executed (e.g., "MainQueryExecution", "CheckQueryValidation") /// Unique batch identifier for tracking the execution /// Human-readable reason for the failure (nullable) /// The underlying exception that caused the failure (nullable) /// Additional contextual details as name-value pairs with optional null-handling /// /// The details parameter accepts tuples with: /// - Name: Display name of the detail /// - Value: String value of the detail (nullable) /// - IgnoreIfNull: If true, the detail is omitted from the message when value is null /// public JobException(string jobName, string processName, string batchId, string? reason, Exception? innerException, params (string Name, string? Value, bool IgnoreIfNull)[] details) : base( Message(jobName, [ ("Process Name", processName, false), ("Batch Id", batchId, false), ("Reason", reason, true), ..details ]), innerException) { JobName = jobName; ProcessName = processName; BatchId = batchId; } /// /// Gets the name of the job that failed /// public string JobName { get; } /// /// Gets the name of the process/stage that was being executed when the failure occurred /// public string ProcessName { get; } /// /// Gets the unique batch identifier for tracking the execution /// public string BatchId { get; } /// /// Generates a formatted error message with job context and details /// /// Name of the job that failed /// Collection of name-value pairs with optional null-handling /// Formatted multi-line error message with visual separators /// /// Message format: /// /// {jobName} could not be completed. /// ───────────────────────────────────────── /// Process Name: {processName} /// Batch Id: {batchId} /// {additional details...} /// ───────────────────────────────────────── /// /// Details with IgnoreIfNull=true are omitted when their value is null. /// internal static string Message(string jobName, IEnumerable<(string Name, string? Value, bool IgnoreIfNull)> details) { var message = new System.Text.StringBuilder(); message.AppendLine($"{jobName} could not be completed."); message.AppendLine("─────────────────────────────────────────"); foreach (var (name, value, ignoreNullValue) in details) { if (ignoreNullValue && value is null) continue; message.AppendLine($" {name}: {value}"); } message.AppendLine("─────────────────────────────────────────"); return message.ToString(); } } }