149 lines
4.5 KiB
Go
149 lines
4.5 KiB
Go
package useCases
|
|
|
|
import (
|
|
"RenewCMS/internal/domain/audit"
|
|
"RenewCMS/internal/domain/image"
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
type PurgeVariantCacheCommand struct {
|
|
Scope image.CachePurgeScope
|
|
Variant string
|
|
ImageID uint32
|
|
}
|
|
|
|
type VariantCachePurgeResult struct {
|
|
Scope image.CachePurgeScope
|
|
Files int
|
|
Bytes int64
|
|
Failed int
|
|
}
|
|
|
|
type PurgeVariantCacheUseCase struct {
|
|
variants image.VariantRepository
|
|
images image.Repository
|
|
cache image.VariantCacheRepository
|
|
files variantCache
|
|
recorder audit.Recorder
|
|
now func() time.Time
|
|
}
|
|
|
|
func NewPurgeVariantCacheUseCase(variants image.VariantRepository, images image.Repository, cache image.VariantCacheRepository, files image.VariantFileRepository, storage image.Storage, now func() time.Time, recorder audit.Recorder) *PurgeVariantCacheUseCase {
|
|
return &PurgeVariantCacheUseCase{variants, images, cache, variantCache{files, storage}, recorder, now}
|
|
}
|
|
|
|
type cachePurgePlan struct {
|
|
filter image.VariantFileFilter
|
|
event audit.Event
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) Purge(ctx context.Context, command PurgeVariantCacheCommand) (VariantCachePurgeResult, error) {
|
|
plan, err := u.plan(command)
|
|
if err != nil {
|
|
return VariantCachePurgeResult{}, err
|
|
}
|
|
result, err := u.purgeMatching(plan.filter)
|
|
result.Scope = command.Scope
|
|
if err != nil {
|
|
recordFailure(ctx, u.recorder, plan.event, err)
|
|
return result, err
|
|
}
|
|
u.record(ctx, plan.event, result)
|
|
return result, nil
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) plan(command PurgeVariantCacheCommand) (cachePurgePlan, error) {
|
|
switch command.Scope {
|
|
case image.CacheScopeAll:
|
|
return cachePurgePlan{event: audit.NewEvent(audit.ActionVariantPurgeAll, audit.CategoryMedia)}, nil
|
|
case image.CacheScopeUnused:
|
|
return u.unusedPlan()
|
|
case image.CacheScopeVariant:
|
|
return u.variantPlan(command.Variant)
|
|
case image.CacheScopeImage:
|
|
return u.imagePlan(command.ImageID)
|
|
default:
|
|
return cachePurgePlan{}, image.ErrCachePurgeScope
|
|
}
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) unusedPlan() (cachePurgePlan, error) {
|
|
variants, err := u.variants.List()
|
|
if err != nil {
|
|
return cachePurgePlan{}, err
|
|
}
|
|
event := audit.NewEvent(audit.ActionVariantPurgeUnused, audit.CategoryMedia)
|
|
filter := image.VariantFileFilter{Unused: &image.UnusedFilter{VariantNames: enabledNames(variants), Cutoff: image.UnusedCutoff(u.now())}}
|
|
return cachePurgePlan{filter: filter, event: event}, nil
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) variantPlan(name string) (cachePurgePlan, error) {
|
|
variant, err := u.variants.Get(name)
|
|
if err != nil {
|
|
return cachePurgePlan{}, err
|
|
}
|
|
if variant.Name != name {
|
|
return cachePurgePlan{}, image.ErrVariantNotFound
|
|
}
|
|
event := audit.NewEvent(audit.ActionVariantPurge, audit.CategoryMedia)
|
|
event.Target = audit.VariantTarget(name)
|
|
return cachePurgePlan{filter: image.VariantFileFilter{VariantName: name}, event: event}, nil
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) imagePlan(id uint32) (cachePurgePlan, error) {
|
|
img, err := u.images.Get(id)
|
|
if err != nil {
|
|
return cachePurgePlan{}, err
|
|
}
|
|
event := audit.NewEvent(audit.ActionVariantPurgeImage, audit.CategoryMedia)
|
|
event.Target = imageTarget(img)
|
|
return cachePurgePlan{filter: image.VariantFileFilter{SourceName: image.StoredName(img.Path)}, event: event}, nil
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) purgeMatching(filter image.VariantFileFilter) (VariantCachePurgeResult, error) {
|
|
var result VariantCachePurgeResult
|
|
var after uint32
|
|
for {
|
|
rows, err := u.cache.ListPage(filter, after, image.CachePurgeBatchSize)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
for _, row := range rows {
|
|
after = row.ID
|
|
if err := u.files.purgeRow(row); err != nil {
|
|
result.Failed++
|
|
continue
|
|
}
|
|
result.Files++
|
|
result.Bytes += row.Size
|
|
}
|
|
if len(rows) < image.CachePurgeBatchSize {
|
|
return result, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func (u *PurgeVariantCacheUseCase) record(ctx context.Context, event audit.Event, result VariantCachePurgeResult) {
|
|
if result.Files == 0 && result.Failed == 0 {
|
|
return
|
|
}
|
|
event.Params = cachePurgeParams(event.Action, result)
|
|
if result.Files == 0 {
|
|
failFrom(ctx, u.recorder, event, GenericFailureReason)
|
|
return
|
|
}
|
|
u.recorder.Record(ctx, event)
|
|
}
|
|
|
|
func cachePurgeParams(action string, result VariantCachePurgeResult) map[string]any {
|
|
params := map[string]any{audit.ParamPurgedFiles: result.Files, audit.ParamPurgedBytes: result.Bytes}
|
|
if action == audit.ActionVariantPurgeUnused {
|
|
params[audit.ParamOlderThanDays] = image.UnusedVariantDays
|
|
}
|
|
if result.Failed > 0 {
|
|
params[audit.ParamFailedFiles] = result.Failed
|
|
}
|
|
return params
|
|
}
|