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  }