enhance utilisation of postgres features
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-04-20 10:19:27 +10:00
parent 98e92a8264
commit 8ccf5a7009
28 changed files with 2836 additions and 422 deletions
+36
View File
@@ -31,6 +31,9 @@ const (
defaultAuthJWTIssuer = "vctp"
defaultAuthJWTAudience = "vctp-api"
defaultAuthClockSkewSeconds = 60
scheduledAggregationEngineGo = "go"
scheduledAggregationEngineSQL = "sql"
)
type Settings struct {
@@ -94,6 +97,11 @@ type SettingsYML struct {
HourlySnapshotTimeoutSeconds int `yaml:"hourly_snapshot_timeout_seconds"`
HourlySnapshotRetrySeconds int `yaml:"hourly_snapshot_retry_seconds"`
HourlySnapshotMaxRetries int `yaml:"hourly_snapshot_max_retries"`
CaptureWriteBatchSize int `yaml:"capture_write_batch_size"`
SnapshotTableCompatMode *bool `yaml:"snapshot_table_compat_mode"`
AsyncReportGeneration *bool `yaml:"async_report_generation"`
PostgresVmHourlyPartitioning *bool `yaml:"postgres_vm_hourly_partitioning_enabled"`
ScheduledAggregationEngine string `yaml:"scheduled_aggregation_engine"`
DailyJobTimeoutSeconds int `yaml:"daily_job_timeout_seconds"`
MonthlyJobTimeoutSeconds int `yaml:"monthly_job_timeout_seconds"`
MonthlyAggregationGranularity string `yaml:"monthly_aggregation_granularity"`
@@ -250,6 +258,29 @@ func applyDefaultsAndValidateSettings(cfg *SettingsYML) error {
if s.AuthClockSkewSeconds == 0 {
s.AuthClockSkewSeconds = defaultAuthClockSkewSeconds
}
if s.CaptureWriteBatchSize <= 0 {
s.CaptureWriteBatchSize = 1000
}
if s.SnapshotTableCompatMode == nil {
v := true
s.SnapshotTableCompatMode = &v
}
if s.AsyncReportGeneration == nil {
v := true
s.AsyncReportGeneration = &v
}
if s.PostgresVmHourlyPartitioning == nil {
v := false
s.PostgresVmHourlyPartitioning = &v
}
s.ScheduledAggregationEngine = strings.ToLower(strings.TrimSpace(s.ScheduledAggregationEngine))
if s.ScheduledAggregationEngine == "" {
s.ScheduledAggregationEngine = scheduledAggregationEngineGo
}
s.MonthlyAggregationGranularity = strings.ToLower(strings.TrimSpace(s.MonthlyAggregationGranularity))
if s.MonthlyAggregationGranularity == "" {
s.MonthlyAggregationGranularity = "daily"
}
s.AuthJWTSigningKey = strings.TrimSpace(s.AuthJWTSigningKey)
s.LDAPBindAddress = strings.TrimSpace(s.LDAPBindAddress)
s.LDAPBaseDN = strings.TrimSpace(s.LDAPBaseDN)
@@ -265,6 +296,11 @@ func applyDefaultsAndValidateSettings(cfg *SettingsYML) error {
if s.AuthClockSkewSeconds < 0 {
return errors.New("settings.auth_clock_skew_seconds must be >= 0")
}
switch s.ScheduledAggregationEngine {
case scheduledAggregationEngineGo, scheduledAggregationEngineSQL:
default:
return fmt.Errorf("settings.scheduled_aggregation_engine must be %q or %q", scheduledAggregationEngineGo, scheduledAggregationEngineSQL)
}
if len(s.AuthGroupRoleMappings) > 0 {
normalized := make(map[string]string, len(s.AuthGroupRoleMappings))
+39
View File
@@ -63,6 +63,45 @@ func TestReadYMLSettingsAppliesAuthDefaults(t *testing.T) {
if got.AuthClockSkewSeconds != defaultAuthClockSkewSeconds {
t.Fatalf("expected default auth_clock_skew_seconds=%d, got %d", defaultAuthClockSkewSeconds, got.AuthClockSkewSeconds)
}
if got.CaptureWriteBatchSize != 1000 {
t.Fatalf("expected default capture_write_batch_size=1000, got %d", got.CaptureWriteBatchSize)
}
if got.SnapshotTableCompatMode == nil || !*got.SnapshotTableCompatMode {
t.Fatalf("expected default snapshot_table_compat_mode=true, got %#v", got.SnapshotTableCompatMode)
}
if got.AsyncReportGeneration == nil || !*got.AsyncReportGeneration {
t.Fatalf("expected default async_report_generation=true, got %#v", got.AsyncReportGeneration)
}
if got.PostgresVmHourlyPartitioning == nil || *got.PostgresVmHourlyPartitioning {
t.Fatalf("expected default postgres_vm_hourly_partitioning_enabled=false, got %#v", got.PostgresVmHourlyPartitioning)
}
if got.ScheduledAggregationEngine != scheduledAggregationEngineGo {
t.Fatalf("expected default scheduled_aggregation_engine=%q, got %q", scheduledAggregationEngineGo, got.ScheduledAggregationEngine)
}
if got.MonthlyAggregationGranularity != "daily" {
t.Fatalf("expected default monthly_aggregation_granularity=daily, got %q", got.MonthlyAggregationGranularity)
}
}
func TestReadYMLSettingsRejectsInvalidScheduledAggregationEngine(t *testing.T) {
tmpDir := t.TempDir()
settingsPath := filepath.Join(tmpDir, "vctp.yml")
content := `settings:
scheduled_aggregation_engine: "hybrid"
`
if err := os.WriteFile(settingsPath, []byte(content), 0o600); err != nil {
t.Fatalf("failed to write settings file: %v", err)
}
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
s := New(logger, settingsPath)
err := s.ReadYMLSettings()
if err == nil {
t.Fatal("expected invalid scheduled_aggregation_engine to fail")
}
if !strings.Contains(strings.ToLower(err.Error()), "scheduled_aggregation_engine") {
t.Fatalf("expected error to mention scheduled_aggregation_engine, got: %v", err)
}
}
func TestReadYMLSettingsRejectsInvalidAuthMode(t *testing.T) {