package useCases import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/domain/image" "context" "slices" ) type GenerateAllResult struct { Generated int Failed int Failures []VariantFailure Items []ImageVariantView } type GenerateAllImageVariantsUseCase struct { images image.Repository variants image.VariantRepository files image.VariantFileRepository renderer image.VariantRenderer generator *ServeVariantUseCase recorder audit.Recorder } func NewGenerateAllImageVariantsUseCase(images image.Repository, variants image.VariantRepository, files image.VariantFileRepository, renderer image.VariantRenderer, generator *ServeVariantUseCase, recorder audit.Recorder) *GenerateAllImageVariantsUseCase { return &GenerateAllImageVariantsUseCase{images, variants, files, renderer, generator, recorder} } func (u *GenerateAllImageVariantsUseCase) Generate(ctx context.Context, id uint32) (GenerateAllResult, error) { img, err := u.images.Get(id) if err != nil { return GenerateAllResult{}, err } if isVectorSource(img) { return GenerateAllResult{}, image.ErrVariantSourceUnsupported } enabled, err := enabledVariants(u.variants) if err != nil { return GenerateAllResult{}, err } storedName := image.StoredName(img.Path) rows, err := currentFiles(u.files, storedName) if err != nil { return GenerateAllResult{}, err } result := GenerateAllResult{Failures: []VariantFailure{}} var firstFailure error for _, variant := range enabled { if isCurrent(variant, rows) { continue } if _, err := u.generator.Generate(ctx, variant, storedName); err != nil { result.Failed++ result.Failures = append(result.Failures, VariantFailure{Name: variant.Name, Cause: generationCause(err)}) if firstFailure == nil { firstFailure = err } continue } result.Generated++ } refreshed, err := currentFiles(u.files, storedName) if err != nil { return GenerateAllResult{}, err } result.Items = viewsOf(enabled, img, refreshed, u.renderer.EncodableFormats()) u.record(ctx, img, result, firstFailure) return result, nil } func (u *GenerateAllImageVariantsUseCase) record(ctx context.Context, img image.Image, result GenerateAllResult, firstFailure error) { if result.Generated == 0 && result.Failed == 0 { return } event := audit.NewEvent(audit.ActionVariantGenerateAll, audit.CategoryMedia) event.Target = imageTarget(img) event.Params = map[string]any{ audit.ParamGenerated: result.Generated, audit.ParamFailed: result.Failed, audit.ParamCauses: distinctCauses(result.Failures), } if result.Generated == 0 { failFrom(ctx, u.recorder, event, reasonFor(firstFailure)) return } u.recorder.Record(ctx, event) } func distinctCauses(failures []VariantFailure) []string { causes := []string{} for _, failure := range failures { if !slices.Contains(causes, failure.Cause) { causes = append(causes, failure.Cause) } } return causes }