diff --git a/ECMJobRunner.Application/Common/Exceptions/InactiveProfileException.cs b/ECMJobRunner.Application/Common/Exceptions/InactiveProfileException.cs index a18ed13..af96b6c 100644 --- a/ECMJobRunner.Application/Common/Exceptions/InactiveProfileException.cs +++ b/ECMJobRunner.Application/Common/Exceptions/InactiveProfileException.cs @@ -6,42 +6,31 @@ namespace ECMJobRunner.Application.Common.Exceptions /// Exception thrown when attempting to execute a job for an inactive profile /// Extends JobException with profile-specific context /// - public class InactiveProfileException : JobException + /// + /// Initializes a new instance of InactiveProfileException + /// + /// ID of the inactive profile + /// Name of the inactive profile (nullable) + /// Unique batch identifier for tracking + /// + /// Use this exception when: + /// - Attempting to trigger DEX job batch for an inactive profile + /// - Attempting to execute individual jobs from an inactive profile + /// - Profile is deactivated during execution + /// + public class InactiveProfileException(long profileId, string? profileName, string batchId) : JobException( + profileId, + jobName: "Profile Execution", + processName: "Profile Active Status Validation", + batchId: batchId, + reason: "The profile is marked as inactive and cannot be executed", + innerException: null, + ("Profile ID", profileId.ToString(), false), + ("Profile Name", profileName, true)) { - /// - /// Initializes a new instance of InactiveProfileException - /// - /// ID of the inactive profile - /// Name of the inactive profile (nullable) - /// Unique batch identifier for tracking - /// - /// Use this exception when: - /// - Attempting to trigger DEX job batch for an inactive profile - /// - Attempting to execute individual jobs from an inactive profile - /// - Profile is deactivated during execution - /// - public InactiveProfileException(long profileId, string? profileName, string batchId) - : base( - jobName: "Profile Execution", - processName: "Profile Active Status Validation", - batchId: batchId, - reason: "The profile is marked as inactive and cannot be executed", - innerException: null, - ("Profile ID", profileId.ToString(), false), - ("Profile Name", profileName, true)) - { - ProfileId = profileId; - ProfileName = profileName; - } - - /// - /// Gets the ID of the inactive profile - /// - public long ProfileId { get; } - /// /// Gets the name of the inactive profile (nullable) /// - public string? ProfileName { get; } + public string? ProfileName { get; } = profileName; } } diff --git a/ECMJobRunner.Application/Common/Exceptions/JobException.cs b/ECMJobRunner.Application/Common/Exceptions/JobException.cs index 74b0db3..a08d80f 100644 --- a/ECMJobRunner.Application/Common/Exceptions/JobException.cs +++ b/ECMJobRunner.Application/Common/Exceptions/JobException.cs @@ -7,53 +7,54 @@ 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( - CreateMessage(jobName, + /// + /// Initializes a new instance of JobException with detailed context information + /// + /// Identifier of the profile associated with the job + /// 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 class JobException(long profileId, string jobName, string processName, string batchId, string? reason, Exception? innerException, params (string Name, string? Value, bool IgnoreIfNull)[] details) + : Exception( + CreateMessage(jobName, [ + ("Profile Id", profileId.ToString(), false), + ("Job Name", jobName, false), ("Process Name", processName, false), ("Batch Id", batchId, false), ("Reason", reason, true), ..details ]), - innerException) - { - JobName = jobName; - ProcessName = processName; - BatchId = batchId; - } + innerException) + { + /// + /// Gets the profile identifier associated with the job execution + /// + public long ProfileId { get; } = profileId; /// /// Gets the name of the job that failed /// - public string JobName { get; } + public string JobName { get; } = jobName; /// /// Gets the name of the process/stage that was being executed when the failure occurred /// - public string ProcessName { get; } + public string ProcessName { get; } = processName; /// /// Gets the unique batch identifier for tracking the execution /// - public string BatchId { get; } + public string BatchId { get; } = batchId; /// /// Generates a formatted error message with job context and details diff --git a/ECMJobRunner.Application/Common/Exceptions/JobHttpException.cs b/ECMJobRunner.Application/Common/Exceptions/JobHttpException.cs index 8243aff..7958584 100644 --- a/ECMJobRunner.Application/Common/Exceptions/JobHttpException.cs +++ b/ECMJobRunner.Application/Common/Exceptions/JobHttpException.cs @@ -6,41 +6,36 @@ namespace ECMJobRunner.Application.Common.Exceptions /// Exception for HTTP client-related job failures (e.g., ReC API calls, REST requests) /// Extends JobException with client library and method context /// - public class JobHttpException : JobException + /// + /// Initializes a new instance of JobHttpException with HTTP client context + /// + /// Identifier of the profile associated with the job + /// Name of the job that failed (e.g., "ReC Request", "API Call") + /// Name of the process/stage being executed + /// Unique batch identifier for tracking + /// Human-readable reason for the failure (nullable) + /// Name of the HTTP client library used (e.g., "ReC.Client", "HttpClient") (nullable) + /// Name of the client method that failed (e.g., "ExecuteAsync", "PostAsync") (nullable) + /// The underlying exception that caused the failure (nullable) + /// + /// Use this exception for HTTP-related failures such as: + /// - ReC API request failures + /// - REST API communication errors + /// - HTTP client timeout/network issues + /// - Authentication/authorization failures + /// + public class JobHttpException(long profileId, string jobName, string processName, string batchId, string? reason, string? clientLibrary, string? clientMethod, Exception? innerException) + : JobException(profileId, jobName, processName, batchId, reason, innerException, ("Client Library", clientLibrary, true), ("Client Method", clientMethod, true)) { - /// - /// Initializes a new instance of JobHttpException with HTTP client context - /// - /// Name of the job that failed (e.g., "ReC Request", "API Call") - /// Name of the process/stage being executed - /// Unique batch identifier for tracking - /// Human-readable reason for the failure (nullable) - /// Name of the HTTP client library used (e.g., "ReC.Client", "HttpClient") (nullable) - /// Name of the client method that failed (e.g., "ExecuteAsync", "PostAsync") (nullable) - /// The underlying exception that caused the failure (nullable) - /// - /// Use this exception for HTTP-related failures such as: - /// - ReC API request failures - /// - REST API communication errors - /// - HTTP client timeout/network issues - /// - Authentication/authorization failures - /// - public JobHttpException(string jobName, string processName, string batchId, string? reason, string? clientLibrary, string? clientMethod, Exception? innerException) : base(jobName, processName, batchId, reason, innerException, - ("Client Library", clientLibrary, true), - ("Client Method", clientMethod, true)) - { - ClientLibrary = clientLibrary; - ClientMethod = clientMethod; - } /// /// Gets the name of the HTTP client library that was used (e.g., "ReC.Client", "HttpClient") /// - public string? ClientLibrary { get; } + public string? ClientLibrary { get; } = clientLibrary; /// /// Gets the name of the client method that failed (e.g., "ExecuteAsync", "PostAsync") /// - public string? ClientMethod { get; } + public string? ClientMethod { get; } = clientMethod; } } diff --git a/ECMJobRunner.Application/Common/Exceptions/JobSqlException.cs b/ECMJobRunner.Application/Common/Exceptions/JobSqlException.cs index cde9537..5f6b115 100644 --- a/ECMJobRunner.Application/Common/Exceptions/JobSqlException.cs +++ b/ECMJobRunner.Application/Common/Exceptions/JobSqlException.cs @@ -6,33 +6,30 @@ namespace ECMJobRunner.Application.Common.Exceptions /// Exception for SQL query execution failures /// Extends JobException with SQL query context for debugging /// - public class JobSqlException : JobException + /// + /// Initializes a new instance of JobSqlException with SQL query context + /// + /// Identifier of the profile associated with the job + /// Name of the job that failed (e.g., "Main Query Execution", "Check Query") + /// Name of the process/stage being executed + /// Unique batch identifier for tracking + /// Human-readable reason for the failure (nullable) + /// The SQL query that failed (nullable, for debugging purposes) + /// The underlying SQL exception (nullable) + /// + /// Use this exception for SQL-related failures such as: + /// - Main query execution errors + /// - Check query validation failures + /// - Database connection issues + /// - SQL syntax errors + /// - Query timeout exceptions + /// + /// The Query property can be logged for debugging but should be handled carefully + /// to avoid exposing sensitive data in production logs. + /// + public class JobSqlException(long profileId, string jobName, string processName, string batchId, string? reason, string? query, Exception? innerException) + : JobException(profileId, jobName, processName, batchId, reason, innerException, ("Query", query, true)) { - /// - /// Initializes a new instance of JobSqlException with SQL query context - /// - /// Name of the job that failed (e.g., "Main Query Execution", "Check Query") - /// Name of the process/stage being executed - /// Unique batch identifier for tracking - /// Human-readable reason for the failure (nullable) - /// The SQL query that failed (nullable, for debugging purposes) - /// The underlying SQL exception (nullable) - /// - /// Use this exception for SQL-related failures such as: - /// - Main query execution errors - /// - Check query validation failures - /// - Database connection issues - /// - SQL syntax errors - /// - Query timeout exceptions - /// - /// The Query property can be logged for debugging but should be handled carefully - /// to avoid exposing sensitive data in production logs. - /// - public JobSqlException(string jobName, string processName, string batchId, string? reason, string? query, Exception? innerException) : base(jobName, processName, batchId, reason, innerException, - ("Query", query, true)) - { - Query = query; - } /// /// Gets the SQL query that failed (nullable) @@ -41,6 +38,6 @@ namespace ECMJobRunner.Application.Common.Exceptions /// This property is marked as virtual to allow derived classes to customize query handling /// (e.g., sanitizing sensitive data, truncating long queries) /// - public virtual string? Query { get; } + public virtual string? Query { get; } = query; } } diff --git a/ECMJobRunner.Application/Profiles/Commands/Behaviors/CheckQueryExecutionBehavior.cs b/ECMJobRunner.Application/Profiles/Commands/Behaviors/CheckQueryExecutionBehavior.cs index a57f7cf..5c87a58 100644 --- a/ECMJobRunner.Application/Profiles/Commands/Behaviors/CheckQueryExecutionBehavior.cs +++ b/ECMJobRunner.Application/Profiles/Commands/Behaviors/CheckQueryExecutionBehavior.cs @@ -71,6 +71,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors { if (result is null) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Check Query", batchId: command.BatchId, @@ -79,6 +80,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors innerException: null); else if (result.ReturnValue <= 0) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Check Query", batchId: command.BatchId, @@ -91,6 +93,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors { if (_options.Error.CheckQuery.OnExecution == ErrorAction.Stop) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Check Query", batchId: command.BatchId, @@ -103,6 +106,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors else if (_options.Error.CheckQuery.IfNullOrWhiteSpace == ErrorAction.Stop) { throw new JobSqlException( + profileId: command.Job.ProfileId, jobName:"Triggering DEX", processName:"Check Query", batchId:command.BatchId, diff --git a/ECMJobRunner.Application/Profiles/Commands/Behaviors/MainQueryExecutionBehavior.cs b/ECMJobRunner.Application/Profiles/Commands/Behaviors/MainQueryExecutionBehavior.cs index c76afd8..f2b4f60 100644 --- a/ECMJobRunner.Application/Profiles/Commands/Behaviors/MainQueryExecutionBehavior.cs +++ b/ECMJobRunner.Application/Profiles/Commands/Behaviors/MainQueryExecutionBehavior.cs @@ -71,6 +71,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors { if (result is null) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Main Query", batchId: command.BatchId, @@ -79,6 +80,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors innerException: null); else if (result.ReturnValue is not null) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Main Query", batchId: command.BatchId, @@ -90,6 +92,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors { if (_options.Error.MainQuery.OnExecution == ErrorAction.Stop) throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Main Query", batchId: command.BatchId, @@ -101,6 +104,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors else if (_options.Error.MainQuery.IfNullOrWhiteSpace == ErrorAction.Stop) { throw new JobSqlException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "Main Query", batchId: command.BatchId, diff --git a/ECMJobRunner.Application/Profiles/Commands/Behaviors/ReCRequestExecutionBehavior.cs b/ECMJobRunner.Application/Profiles/Commands/Behaviors/ReCRequestExecutionBehavior.cs index a764ec9..263bebc 100644 --- a/ECMJobRunner.Application/Profiles/Commands/Behaviors/ReCRequestExecutionBehavior.cs +++ b/ECMJobRunner.Application/Profiles/Commands/Behaviors/ReCRequestExecutionBehavior.cs @@ -67,6 +67,7 @@ namespace ECMJobRunner.Application.Profiles.Commands.Behaviors if (_options.Error.ReCRequest.OnSending == ErrorAction.Stop) { throw new JobHttpException( + profileId: command.Job.ProfileId, jobName: "Triggering DEX", processName: "ReC Http Request", batchId: command.BatchId,