github.com/quay/claircore@v1.5.28/datastore/postgres/manifestscanned.go (about)

     1  package postgres
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/prometheus/client_golang/prometheus"
     9  	"github.com/prometheus/client_golang/prometheus/promauto"
    10  
    11  	"github.com/quay/claircore"
    12  	"github.com/quay/claircore/indexer"
    13  )
    14  
    15  var (
    16  	manifestScannedCounter = promauto.NewCounterVec(
    17  		prometheus.CounterOpts{
    18  			Namespace: "claircore",
    19  			Subsystem: "indexer",
    20  			Name:      "manifestscanned_total",
    21  			Help:      "Total number of database queries issued in the ManifestScanned method.",
    22  		},
    23  		[]string{"query"},
    24  	)
    25  
    26  	manifestScannedDuration = promauto.NewHistogramVec(
    27  		prometheus.HistogramOpts{
    28  			Namespace: "claircore",
    29  			Subsystem: "indexer",
    30  			Name:      "manifestscanned_duration_seconds",
    31  			Help:      "The duration of all queries issued in the ManifestScanned method",
    32  		},
    33  		[]string{"query"},
    34  	)
    35  )
    36  
    37  // ManifestScanned determines if a manifest has been scanned by ALL the provided
    38  // scanners.
    39  func (s *IndexerStore) ManifestScanned(ctx context.Context, hash claircore.Digest, vs indexer.VersionedScanners) (bool, error) {
    40  	const (
    41  		selectScanned = `
    42  		SELECT scanner_id
    43  		FROM scanned_manifest
    44  				 JOIN manifest ON scanned_manifest.manifest_id = manifest.id
    45  		WHERE manifest.hash = $1;
    46  		`
    47  	)
    48  
    49  	// get the ids of the scanners we are testing for.
    50  	expectedIDs, err := s.selectScanners(ctx, vs)
    51  	if err != nil {
    52  		return false, err
    53  	}
    54  
    55  	// get a map of the found ids which have scanned this package
    56  	foundIDs := map[int64]struct{}{}
    57  
    58  	start := time.Now()
    59  	rows, err := s.pool.Query(ctx, selectScanned, hash)
    60  	if err != nil {
    61  		return false, fmt.Errorf("failed to select scanner IDs for manifest: %w", err)
    62  	}
    63  	manifestScannedCounter.WithLabelValues("selectScanned").Add(1)
    64  	manifestScannedDuration.WithLabelValues("selectScanned").Observe(time.Since(start).Seconds())
    65  	defer rows.Close()
    66  	var t int64
    67  	for rows.Next() {
    68  		if err := rows.Scan(&t); err != nil {
    69  			return false, fmt.Errorf("failed to select scanner IDs for manifest: %w", err)
    70  		}
    71  		foundIDs[t] = struct{}{}
    72  	}
    73  	if err := rows.Err(); err != nil {
    74  		return false, fmt.Errorf("failed to select scanner IDs for manifest: %w", err)
    75  	}
    76  
    77  	// compare the expectedIDs array with our foundIDs. if we get a lookup
    78  	// miss we can say the manifest has not been scanned by all the layers provided
    79  	for _, id := range expectedIDs {
    80  		if _, ok := foundIDs[id]; !ok {
    81  			return false, nil
    82  		}
    83  	}
    84  
    85  	return true, nil
    86  }