feat(config): add DexJobOptions configuration system and update placeholder pattern

- Add SectionName constant to DexJobOptions
- Update placeholder pattern to {#INT#BATCH_ID}
- Add DexJob configuration section to appsettings.json
- Add IConfiguration parameter to DependencyInjection for options binding
- Add Microsoft.Extensions.Options.ConfigurationExtensions package for .NET Framework 4.8
- Improve code documentation and move class into namespace
This commit is contained in:
2026-08-04 16:33:26 +02:00
parent 73db8fbd27
commit f75524f85d
4 changed files with 111 additions and 76 deletions

View File

@@ -1,105 +1,109 @@
using ECMJobRunner.Application.Common.Constants;
using System.Text.RegularExpressions;
namespace ECMJobRunner.Application.Common.Options
namespace ECMJobRunner.Application.Common.Options;
/// <summary>
/// Configuration options for DEX job execution
/// </summary>
public class DexJobOptions
{
/// <summary>
/// Configuration options for DEX job execution
/// The configuration section name used to bind this options class from application settings
/// </summary>
public class DexJobOptions
public const string SectionName = "DexJob";
/// <summary>
/// Error handling options for DEX job operations
/// </summary>
public record DexJobErrorHandlingOptions
{
/// <summary>
/// Error handling options for DEX job operations
/// Error handling options for SQL query execution
/// </summary>
public record DexJobErrorHandlingOptions
public record SqlQueryErrorHandlingOptions
{
/// <summary>
/// Error handling options for SQL query execution
/// Action to take when query execution fails
/// </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;
}
public ErrorAction OnExecution { get; set; } = ErrorAction.Stop;
/// <summary>
/// Error handling options for HTTP requests
/// Action to take when query is null or whitespace
/// </summary>
public record HttpRequestErrorHandlingOptions
{
/// <summary>
/// Action to take when HTTP request fails
/// </summary>
public ErrorAction OnSending { get; set; } = ErrorAction.Stop;
}
public ErrorAction IfNullOrWhiteSpace { get; set; } = ErrorAction.Ignore;
/// <summary>
/// Error handling for main SQL query
/// Action to take when query returns unexpected result
/// </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();
public ErrorAction OnUnexpectedResult { get; set; } = ErrorAction.Stop;
}
/// <summary>
/// Error handling configuration
/// Error handling options for HTTP requests
/// </summary>
public DexJobErrorHandlingOptions Error { get; set; } = new();
/// <summary>
/// Placeholder configuration for dynamic value replacement
/// </summary>
public record PlaceHolderOptions
public record HttpRequestErrorHandlingOptions
{
/// <summary>
/// Configuration for a single placeholder
/// Action to take when HTTP request fails
/// </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
};
public ErrorAction OnSending { get; set; } = ErrorAction.Stop;
}
/// <summary>
/// Placeholder configuration
/// Error handling for main SQL query
/// </summary>
public PlaceHolderOptions Placeholders { get; set; } = new();
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();
}

View File

@@ -1,5 +1,7 @@
using ECMJobRunner.Application.Common.Options;
using ECMJobRunner.Application.Profiles.Commands.Behaviors;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ReC.Client;
using System.Reflection;
@@ -17,8 +19,9 @@ namespace ECMJobRunner.Application
/// </summary>
/// <param name="services">The service collection</param>
/// <param name="recClientApiUrl">The base URL for the ReC client API</param>
/// <param name="configuration">The application configuration</param>
/// <returns>The service collection for chaining</returns>
public static IServiceCollection AddJobRunnerServices(this IServiceCollection services, string recClientApiUrl)
public static IServiceCollection AddJobRunnerServices(this IServiceCollection services, string recClientApiUrl, IConfiguration configuration)
{
var assembly = Assembly.GetExecutingAssembly();
@@ -36,6 +39,9 @@ namespace ECMJobRunner.Application
opt.LogSuccessfulRequests = true;
});
// Configure DexJobOptions from appsettings.json
services.Configure<DexJobOptions>(configuration.GetSection(DexJobOptions.SectionName));
// Register pipeline behaviors in execution order
// Order matters: MainQuery -> CheckQuery -> ReCRequest
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(JobExceptionHandlingBehavior<,>));

View File

@@ -17,7 +17,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ReC.Client" Version="2.0.0-beta" />
<PackageReference Include="ReC.Client" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
@@ -31,6 +31,8 @@
<!-- MediatR for .NET Framework 4.8 -->
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<!-- Options configuration binding for .NET Framework 4.8 -->
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">

View File

@@ -23,5 +23,28 @@
},
"ProfileWorker": {
"IntervalMS": 60000
},
"DexJob": {
"Error": {
"MainQuery": {
"OnExecution": "Stop",
"IfNullOrWhiteSpace": "Ignore",
"OnUnexpectedResult": "Stop"
},
"CheckQuery": {
"OnExecution": "Stop",
"IfNullOrWhiteSpace": "Ignore",
"OnUnexpectedResult": "Stop"
},
"ReCRequest": {
"OnSending": "Stop"
}
},
"Placeholders": {
"BatchId": {
"Pattern": "{#INT#BATCH_ID}",
"RegexOptions": "IgnoreCase"
}
}
}
}