feat(historian): SQL Server retention purge (RetentionDays, Primary-gated, applock) (#667)

This commit is contained in:
Joseph Doherty
2026-10-11 08:21:30 -04:00
parent db6a53036b
commit 924eff8d3c
13 changed files with 602 additions and 2 deletions
@@ -0,0 +1,62 @@
using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer.Tests;
public sealed class SqlServerHistorianRetentionOptionsTests
{
private static SqlServerHistorianOptions Valid() => new() { ConnectionString = "Server=x" };
[Fact]
public void Retention_is_off_by_default_with_sane_defaults()
{
var o = Valid();
o.RetentionDays.ShouldBeNull();
o.PurgeInterval.ShouldBe(TimeSpan.FromHours(1));
o.PurgeBatchSize.ShouldBe(4000);
o.Validate().ShouldBeEmpty();
}
[Theory]
[InlineData(0)]
[InlineData(-5)]
public void Non_positive_RetentionDays_is_rejected(int days)
{
var o = Valid();
o.RetentionDays = days;
o.Validate().ShouldContain(e => e.Contains("RetentionDays"));
}
[Fact]
public void Positive_RetentionDays_is_valid()
{
var o = Valid();
o.RetentionDays = 30;
o.Validate().ShouldBeEmpty();
}
[Fact]
public void Bad_interval_and_batch_are_rejected()
{
var o = Valid();
o.PurgeInterval = TimeSpan.Zero;
o.PurgeBatchSize = 0;
var errors = o.Validate();
errors.ShouldContain(e => e.Contains("PurgeInterval"));
errors.ShouldContain(e => e.Contains("PurgeBatchSize"));
}
[Fact]
public void Provider_creates_retention_only_when_RetentionDays_set()
{
var o = Valid();
new SqlServerHistorianProvider(o).CreateRetention(new EmptyServices()).ShouldBeNull();
o.RetentionDays = 7;
new SqlServerHistorianProvider(o).CreateRetention(new EmptyServices()).ShouldNotBeNull();
}
private sealed class EmptyServices : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
}