fix(options): eager startup validation for AuditLog central sub-options — PartitionMaintenance, Purge, Reconciliation (plan R2-08 T6, arch-review 08r2 NF4)
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
using ZB.MOM.WW.Configuration;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central;
|
||||
|
||||
/// <summary>
|
||||
/// Validates <see cref="AuditLogPartitionMaintenanceOptions"/> at host startup
|
||||
/// (arch-review 08 round 2 NF4). A zero tick interval spins the maintenance
|
||||
/// hosted service; a zero look-ahead leaves <c>pf_AuditLog_Month</c> without a
|
||||
/// future monthly boundary, risking inserts into the unbounded tail partition.
|
||||
/// </summary>
|
||||
public sealed class AuditLogPartitionMaintenanceOptionsValidator
|
||||
: OptionsValidatorBase<AuditLogPartitionMaintenanceOptions>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Validate(ValidationBuilder builder, AuditLogPartitionMaintenanceOptions options)
|
||||
{
|
||||
builder.RequireThat(options.IntervalSeconds > 0,
|
||||
$"AuditLog:PartitionMaintenance:{nameof(AuditLogPartitionMaintenanceOptions.IntervalSeconds)} " +
|
||||
$"({options.IntervalSeconds}) must be > 0.");
|
||||
|
||||
builder.RequireThat(options.LookaheadMonths > 0,
|
||||
$"AuditLog:PartitionMaintenance:{nameof(AuditLogPartitionMaintenanceOptions.LookaheadMonths)} " +
|
||||
$"({options.LookaheadMonths}) must be > 0.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ZB.MOM.WW.Configuration;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central;
|
||||
|
||||
/// <summary>
|
||||
/// Validates <see cref="AuditLogPurgeOptions"/> at host startup (arch-review 08
|
||||
/// round 2 NF4). The class self-clamps at resolve time, but a plainly-wrong
|
||||
/// config (zero cadence, zero batch, zero maintenance-command timeout) should
|
||||
/// still fail the boot so the operator learns immediately.
|
||||
/// <see cref="AuditLogPurgeOptions.IntervalOverride"/> is test-only (per the
|
||||
/// class remarks) and is deliberately not validated.
|
||||
/// </summary>
|
||||
public sealed class AuditLogPurgeOptionsValidator : OptionsValidatorBase<AuditLogPurgeOptions>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Validate(ValidationBuilder builder, AuditLogPurgeOptions options)
|
||||
{
|
||||
builder.RequireThat(options.IntervalHours > 0,
|
||||
$"AuditLog:Purge:{nameof(AuditLogPurgeOptions.IntervalHours)} " +
|
||||
$"({options.IntervalHours}) must be > 0.");
|
||||
|
||||
// Backing field for the documented "ChannelPurgeBatchSize" config key.
|
||||
builder.RequireThat(options.ChannelPurgeBatchSizeConfigured > 0,
|
||||
$"AuditLog:Purge:{nameof(AuditLogPurgeOptions.ChannelPurgeBatchSizeConfigured)} " +
|
||||
$"(config key ChannelPurgeBatchSize = {options.ChannelPurgeBatchSizeConfigured}) must be > 0.");
|
||||
|
||||
builder.RequireThat(options.MaintenanceCommandTimeoutMinutes > 0,
|
||||
$"AuditLog:Purge:{nameof(AuditLogPurgeOptions.MaintenanceCommandTimeoutMinutes)} " +
|
||||
$"({options.MaintenanceCommandTimeoutMinutes}) must be > 0.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ZB.MOM.WW.Configuration;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central;
|
||||
|
||||
/// <summary>
|
||||
/// Validates <see cref="SiteAuditReconciliationOptions"/> at host startup
|
||||
/// (arch-review 08 round 2 NF4). A zero tick interval spins the reconciliation
|
||||
/// singleton, a zero batch pulls nothing per RPC, and a zero stalled-cycle
|
||||
/// threshold would fire the stalled signal on the first non-draining cycle.
|
||||
/// <see cref="SiteAuditReconciliationOptions.ReconciliationIntervalOverride"/>
|
||||
/// is test-only (per the class remarks) and is deliberately not validated.
|
||||
/// </summary>
|
||||
public sealed class SiteAuditReconciliationOptionsValidator
|
||||
: OptionsValidatorBase<SiteAuditReconciliationOptions>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Validate(ValidationBuilder builder, SiteAuditReconciliationOptions options)
|
||||
{
|
||||
builder.RequireThat(options.ReconciliationIntervalSeconds > 0,
|
||||
$"AuditLog:Reconciliation:{nameof(SiteAuditReconciliationOptions.ReconciliationIntervalSeconds)} " +
|
||||
$"({options.ReconciliationIntervalSeconds}) must be > 0.");
|
||||
|
||||
builder.RequireThat(options.BatchSize > 0,
|
||||
$"AuditLog:Reconciliation:{nameof(SiteAuditReconciliationOptions.BatchSize)} " +
|
||||
$"({options.BatchSize}) must be > 0.");
|
||||
|
||||
builder.RequireThat(options.StalledAfterNonDrainingCycles > 0,
|
||||
$"AuditLog:Reconciliation:{nameof(SiteAuditReconciliationOptions.StalledAfterNonDrainingCycles)} " +
|
||||
$"({options.StalledAfterNonDrainingCycles}) must be > 0.");
|
||||
}
|
||||
}
|
||||
@@ -368,8 +368,8 @@ public static class ServiceCollectionExtensions
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
ArgumentNullException.ThrowIfNull(config);
|
||||
|
||||
services.AddOptions<AuditLogPartitionMaintenanceOptions>()
|
||||
.Bind(config.GetSection(PartitionMaintenanceSectionName));
|
||||
services.AddValidatedOptions<AuditLogPartitionMaintenanceOptions,
|
||||
AuditLogPartitionMaintenanceOptionsValidator>(config, PartitionMaintenanceSectionName);
|
||||
services.AddHostedService<AuditLogPartitionMaintenanceService>();
|
||||
|
||||
// I1 (review): bind the two central-singleton options HERE rather than in
|
||||
@@ -385,10 +385,10 @@ public static class ServiceCollectionExtensions
|
||||
// 5 min reconciliation tick); production exposes IntervalHours /
|
||||
// ReconciliationIntervalSeconds only — the test-only *Override knobs are
|
||||
// not intended to be set from config (see the options classes' remarks).
|
||||
services.AddOptions<AuditLogPurgeOptions>()
|
||||
.Bind(config.GetSection(PurgeSectionName));
|
||||
services.AddOptions<SiteAuditReconciliationOptions>()
|
||||
.Bind(config.GetSection(ReconciliationSectionName));
|
||||
services.AddValidatedOptions<AuditLogPurgeOptions, AuditLogPurgeOptionsValidator>(
|
||||
config, PurgeSectionName);
|
||||
services.AddValidatedOptions<SiteAuditReconciliationOptions, SiteAuditReconciliationOptionsValidator>(
|
||||
config, ReconciliationSectionName);
|
||||
|
||||
// Central health snapshot — a single object
|
||||
// that owns the CentralAuditWriteFailures + AuditRedactionFailure
|
||||
|
||||
Reference in New Issue
Block a user