feat(datasync): add ScheduleDefaults to PipelinesRoot

Add ScheduleDefaults? parameter to PipelinesRoot record and
EffectiveScheduleDefaults computed property that returns
defaults when null.

Updates all existing test usages to include the new parameter.
This commit is contained in:
Joseph Doherty
2026-01-07 00:33:18 -05:00
parent 1318dce18a
commit 15cfc1a010
3 changed files with 105 additions and 0 deletions
@@ -2,9 +2,11 @@ namespace JdeScoping.DataSync.Configuration;
public record PipelinesRoot(
PipelineSettings? Settings, // Optional - defaults applied if missing
ScheduleDefaults? ScheduleDefaults, // Optional - defaults applied if missing
Dictionary<string, PipelineConfig> Pipelines)
{
public PipelineSettings EffectiveSettings => Settings ?? new PipelineSettings();
public ScheduleDefaults EffectiveScheduleDefaults => ScheduleDefaults ?? new ScheduleDefaults();
}
public record PipelineSettings(
@@ -0,0 +1,84 @@
using JdeScoping.DataSync.Configuration;
using Shouldly;
namespace JdeScoping.DataSync.Tests.Configuration;
public class PipelinesRootTests
{
[Fact]
public void EffectiveScheduleDefaults_WhenNull_ReturnsDefaults()
{
var root = new PipelinesRoot(null, null, new Dictionary<string, PipelineConfig>());
var defaults = root.EffectiveScheduleDefaults;
defaults.ShouldNotBeNull();
defaults.Mass.IntervalMinutes.ShouldBe(10080);
defaults.Daily.IntervalMinutes.ShouldBe(1440);
defaults.Hourly.IntervalMinutes.ShouldBe(60);
}
[Fact]
public void EffectiveScheduleDefaults_WhenProvided_ReturnsProvided()
{
var customDefaults = new ScheduleDefaults
{
Mass = new ScheduleConfig { IntervalMinutes = 20000 }
};
var root = new PipelinesRoot(null, customDefaults, new Dictionary<string, PipelineConfig>());
var defaults = root.EffectiveScheduleDefaults;
defaults.Mass.IntervalMinutes.ShouldBe(20000);
}
[Fact]
public void EffectiveSettings_WhenNull_ReturnsDefaults()
{
var root = new PipelinesRoot(null, null, new Dictionary<string, PipelineConfig>());
var settings = root.EffectiveSettings;
settings.ShouldNotBeNull();
settings.Timezone.ShouldBe("UTC");
}
[Fact]
public void EffectiveSettings_WhenProvided_ReturnsProvided()
{
var customSettings = new PipelineSettings("America/New_York");
var root = new PipelinesRoot(customSettings, null, new Dictionary<string, PipelineConfig>());
var settings = root.EffectiveSettings;
settings.Timezone.ShouldBe("America/New_York");
}
[Fact]
public void Pipelines_WhenProvided_StoresCorrectly()
{
var pipelines = new Dictionary<string, PipelineConfig>
{
["TestTable"] = CreateMinimalPipelineConfig()
};
var root = new PipelinesRoot(null, null, pipelines);
root.Pipelines.ShouldContainKey("TestTable");
root.Pipelines["TestTable"].Destination.Table.ShouldBe("TestTable");
}
private static PipelineConfig CreateMinimalPipelineConfig()
{
return new PipelineConfig(
new SourceConfig("lotfinder", "SELECT 1", null, null),
new Dictionary<string, SyncModeConfig>
{
["mass"] = new SyncModeConfig(null, true, true),
["incremental"] = new SyncModeConfig("-1d")
},
null,
new DestinationConfig("TestTable", ["Id"], null),
null,
null);
}
}
@@ -132,6 +132,7 @@ public class EtlPipelineFactoryTests
// Arrange - config with only mass mode
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -201,6 +202,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -227,6 +229,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -261,6 +264,7 @@ public class EtlPipelineFactoryTests
// Arrange - no destination override
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -308,6 +312,7 @@ public class EtlPipelineFactoryTests
// Arrange - mass mode with bulkMerge override
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -340,6 +345,7 @@ public class EtlPipelineFactoryTests
// Arrange - bulkMerge needs matchColumns
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -374,6 +380,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -409,6 +416,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -444,6 +452,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -479,6 +488,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -517,6 +527,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -548,6 +559,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -579,6 +591,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -610,6 +623,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -648,6 +662,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -683,6 +698,7 @@ public class EtlPipelineFactoryTests
// Arrange - null settings should use defaults
var config = new PipelinesRoot(
null, // Null settings
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -718,6 +734,7 @@ public class EtlPipelineFactoryTests
// Arrange
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -748,6 +765,7 @@ public class EtlPipelineFactoryTests
// Arrange - null offset should be valid (no date filtering)
var config = new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(
@@ -781,6 +799,7 @@ public class EtlPipelineFactoryTests
{
return new PipelinesRoot(
new PipelineSettings("UTC"),
null,
new Dictionary<string, PipelineConfig>
{
["TestTable"] = new PipelineConfig(