github.com/quay/claircore@v1.5.28/datastore/postgres/deletemanifests.go (about) 1 package postgres 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 8 "github.com/jackc/pgx/v4" 9 "github.com/prometheus/client_golang/prometheus" 10 "github.com/prometheus/client_golang/prometheus/promauto" 11 "github.com/quay/zlog" 12 13 "github.com/quay/claircore" 14 ) 15 16 var ( 17 deleteManifestsCounter = promauto.NewCounterVec( 18 prometheus.CounterOpts{ 19 Namespace: "claircore", 20 Subsystem: "indexer", 21 Name: "deletemanifests_total", 22 Help: "Total number of calls to the DeleteManifests method.", 23 }, 24 []string{"action", "success"}, 25 ) 26 deleteManifestsDuration = promauto.NewHistogramVec( 27 prometheus.HistogramOpts{ 28 Namespace: "claircore", 29 Subsystem: "indexer", 30 Name: "deletemanifests_duration_seconds", 31 Help: "The duration of taken by the DeleteManifests method.", 32 }, 33 []string{"action", "success"}, 34 ) 35 ) 36 37 func (s *IndexerStore) DeleteManifests(ctx context.Context, ds ...claircore.Digest) ([]claircore.Digest, error) { 38 ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/DeleteManifests") 39 const ( 40 getManifestID = `SELECT id FROM manifest WHERE hash = $1` 41 getLayers = `SELECT layer_id FROM manifest_layer WHERE manifest_id = $1;` 42 deleteManifest = `DELETE FROM manifest WHERE id = $1;` 43 deleteLayers = `DELETE FROM 44 layer 45 WHERE 46 id IN ( 47 SELECT 48 l.id 49 FROM 50 layer l 51 LEFT JOIN manifest_layer ml ON l.id = ml.layer_id 52 WHERE 53 l.id = $1 54 AND ml.layer_id IS NULL 55 );` 56 ) 57 58 var err error 59 defer promTimer(deleteManifestsDuration, "deleteManifest", &err)() 60 defer func(e *error) { 61 deleteManifestsCounter.WithLabelValues("deleteManifest", success(*e)).Inc() 62 }(&err) 63 deletedManifests := make([]claircore.Digest, 0, len(ds)) 64 for _, d := range ds { 65 s.pool.BeginFunc(ctx, func(tx pgx.Tx) error { 66 defer promTimer(deleteManifestsDuration, "deleteLayers", &err)() 67 defer func(e *error) { 68 deleteManifestsCounter.WithLabelValues("deleteLayers", success(*e)).Inc() 69 }(&err) 70 // Get manifest ID 71 var manifestID int64 72 err := tx.QueryRow(ctx, getManifestID, d).Scan(&manifestID) 73 switch { 74 case errors.Is(err, nil): 75 case errors.Is(err, pgx.ErrNoRows): 76 // Currently a silent error, go on to the next 77 return nil 78 default: 79 return fmt.Errorf("unable query manifest: %w", err) 80 } 81 82 // Get all layer IDs 83 lRows, err := tx.Query(ctx, getLayers, manifestID) 84 if err != nil { 85 return fmt.Errorf("unable to query layers: %w", err) 86 } 87 defer lRows.Close() 88 lIDs := []int64{} 89 for lRows.Next() { 90 var layerID int64 91 err = lRows.Scan(&layerID) 92 if err != nil { 93 return fmt.Errorf("unable to scan layer ID: %w", err) 94 } 95 lIDs = append(lIDs, layerID) 96 } 97 if err := lRows.Err(); err != nil { 98 return fmt.Errorf("error reading layer data: %w", err) 99 } 100 101 // Delete manifest 102 _, err = tx.Exec(ctx, deleteManifest, manifestID) 103 if err != nil { 104 return fmt.Errorf("unable to delete manifest: %w", err) 105 } 106 // Delete eligible layers 107 for _, lID := range lIDs { 108 tag, err := tx.Exec(ctx, deleteLayers, lID) 109 if err != nil { 110 return fmt.Errorf("unable check layer usage: %w", err) 111 } 112 ra := tag.RowsAffected() 113 zlog.Debug(ctx). 114 Int64("count", ra). 115 Str("manifest", d.String()). 116 Msg("deleted layers for manifest") 117 } 118 deletedManifests = append(deletedManifests, d) 119 return nil 120 }) 121 } 122 zlog.Debug(ctx). 123 Int("count", len(deletedManifests)). 124 Int("nonexistant", len(ds)-len(deletedManifests)). 125 Msg("deleted manifests") 126 return deletedManifests, nil 127 }