Files
nexarch/internal/migration/auditcontinuity/postgres.go
T
patrickandClaude Sonnet 5.5 5b8c20777d refactor: Pruefgate-Pakete nach Funktion benannt, migration* gruppiert
- dms/ai/workflow: qa0x-Pakete nach internal/gates/<thema> verschoben, Paketname = Thema
- internal/migration{acl,audit,...} -> internal/migration/{acl,audit,...}
- Importpfade, Gate-Skripte und zwei relative Migrationspfade angepasst
- keine Logikaenderung; mail-Gates bewusst unveraendert (pfadabhaengig)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 12:44:21 +01:00

67 lines
2.2 KiB
Go

package migrationauditcontinuity
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
// PostgresSourceStatsProvider liest Anzahl/aeltesten/neuesten Zeitstempel
// aus legacy_audit_log_staging, ueber tenant_migration_map auf den
// Tenant-Slug aufgeloest — Quelle beider Altsysteme in einer Abfrage, da ein
// Tenant genau eine der beiden source_tenant_id-Spalten belegt
// (CHECK tenant_migration_map_source_present in COR-01/COR-02).
type PostgresSourceStatsProvider struct {
RegistryPool *pgxpool.Pool
}
func (p PostgresSourceStatsProvider) Stats(ctx context.Context, tenantSlug string) (AuditStats, error) {
var count int64
var oldest, newest *time.Time
err := p.RegistryPool.QueryRow(ctx, `
SELECT count(l.*), min(l.occurred_at), max(l.occurred_at)
FROM legacy_audit_log_staging l
JOIN tenant_migration_map t
ON (l.source_system = 'archivmail' AND t.archivmail_tenant_id = l.source_tenant_id)
OR (l.source_system = 'archivdms' AND t.archivdms_tenant_id = l.source_tenant_id)
WHERE t.slug = $1
`, tenantSlug).Scan(&count, &oldest, &newest)
if err != nil {
return AuditStats{}, fmt.Errorf("migrationauditcontinuity: quellstatistik fuer tenant %q lesen: %w", tenantSlug, err)
}
return toStats(tenantSlug, count, oldest, newest), nil
}
// PostgresTargetStatsProvider liest Anzahl/aeltesten/neuesten Zeitstempel
// direkt aus audit_events (COR-05-Ziel) je Tenant-Slug.
type PostgresTargetStatsProvider struct {
AuditPool *pgxpool.Pool
}
func (p PostgresTargetStatsProvider) Stats(ctx context.Context, tenantSlug string) (AuditStats, error) {
var count int64
var oldest, newest *time.Time
err := p.AuditPool.QueryRow(ctx, `
SELECT count(*), min(occurred_at), max(occurred_at)
FROM audit_events
WHERE tenant_slug = $1
`, tenantSlug).Scan(&count, &oldest, &newest)
if err != nil {
return AuditStats{}, fmt.Errorf("migrationauditcontinuity: zielstatistik fuer tenant %q lesen: %w", tenantSlug, err)
}
return toStats(tenantSlug, count, oldest, newest), nil
}
func toStats(tenantSlug string, count int64, oldest, newest *time.Time) AuditStats {
stats := AuditStats{TenantSlug: tenantSlug, Count: count}
if oldest != nil {
stats.Oldest = *oldest
}
if newest != nil {
stats.Newest = *newest
}
return stats
}