package pipeline import ( "fmt" "gitea.maximumdirect.net/eric/notarius/internal/core/source" "gitea.maximumdirect.net/eric/notarius/internal/framework/contracts" frameworkdiagnostics "gitea.maximumdirect.net/eric/notarius/internal/framework/diagnostics" ) func terminalDiagnosticGroups(terminal producerAttemptTerminal, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) { return promoteCheckpointDiagnostics(terminalCheckpointDiagnostics(terminal), origin, chunk) } func terminalCheckpointDiagnostics(terminal producerAttemptTerminal) []CheckpointDiagnostic { diagnostics := make([]CheckpointDiagnostic, 0, len(terminal.Diagnostics)) for _, diagnostic := range terminal.Diagnostics { diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: diagnostic}) } for _, record := range terminal.Validation.Diagnostics() { diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: record.diagnostic, ValidatorKey: record.validatorName}) } if terminal.Action == producerTerminalIncompleteAccepted { for _, record := range incompleteValidationDiagnostics(terminal.Validation) { diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: record.diagnostic, ValidatorKey: record.validatorName}) } } return cloneCheckpointDiagnostics(diagnostics) } func promoteCheckpointDiagnostics(diagnostics []CheckpointDiagnostic, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) { groups := make([]contracts.DiagnosticGroup, 0, len(diagnostics)) for _, record := range diagnostics { validatorOrigin := origin validatorOrigin.ValidatorKey = record.ValidatorKey promoted, err := promoteProducerDiagnostics([]contracts.ProducerDiagnostic{record.Diagnostic}, validatorOrigin, chunk) if err != nil { return nil, fmt.Errorf("checkpoint diagnostic: %w", err) } groups = append(groups, promoted...) } return groups, nil } func cloneCheckpointDiagnostics(diagnostics []CheckpointDiagnostic) []CheckpointDiagnostic { if len(diagnostics) == 0 { return nil } cloned := make([]CheckpointDiagnostic, len(diagnostics)) for index, diagnostic := range diagnostics { cloned[index] = CheckpointDiagnostic{ Diagnostic: contracts.CloneProducerDiagnostics([]contracts.ProducerDiagnostic{diagnostic.Diagnostic})[0], ValidatorKey: diagnostic.ValidatorKey, } } return cloned } func promoteProducerDiagnostics(diagnostics []contracts.ProducerDiagnostic, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) { if err := contracts.ValidateProducerDiagnostics(diagnostics); err != nil { return nil, err } if len(diagnostics) == 0 { return nil, nil } groups := make([]contracts.DiagnosticGroup, len(diagnostics)) for index, diagnostic := range diagnostics { group := contracts.DiagnosticGroup{ Disposition: diagnostic.Disposition, Category: diagnostic.Category, ReasonCode: diagnostic.ReasonCode, Origin: origin, OccurrenceCount: diagnostic.OccurrenceCount, Samples: cloneDiagnosticSamples(diagnostic.Samples, chunk), OmittedSampleCount: diagnostic.OmittedSampleCount, } if err := group.Validate(); err != nil { return nil, err } groups[index] = group } return groups, nil } func cloneDiagnosticSamples(samples []contracts.DiagnosticSample, chunk *source.Chunk) []contracts.DiagnosticSample { if len(samples) == 0 { return nil } cloned := make([]contracts.DiagnosticSample, len(samples)) for index, sample := range samples { if chunk != nil { chunkIndex := chunk.Index sample.ChunkID = chunk.ID sample.ChunkIndex = &chunkIndex } else if sample.ChunkIndex != nil { chunkIndex := *sample.ChunkIndex sample.ChunkIndex = &chunkIndex } cloned[index] = sample } return cloned } func appendDiagnosticGroups(output *RunOutput, groups []contracts.DiagnosticGroup) { if output == nil || len(groups) == 0 { return } cloned := contracts.CloneDiagnosticCollection(contracts.DiagnosticCollection{Groups: groups}).Groups output.diagnosticGroups = append(output.diagnosticGroups, cloned...) } func finalizeDiagnostics(output *RunOutput) error { if output == nil { return nil } aggregator := frameworkdiagnostics.Aggregator{} for _, group := range output.diagnosticGroups { if err := aggregator.Add(group); err != nil { return err } } output.Diagnostics = aggregator.Collection() return nil }