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

     1  package postgres
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/jackc/pgx/v4"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/prometheus/client_golang/prometheus/promauto"
    12  
    13  	"github.com/quay/claircore"
    14  	"github.com/quay/claircore/indexer"
    15  )
    16  
    17  var (
    18  	layerScannedCounter = promauto.NewCounterVec(
    19  		prometheus.CounterOpts{
    20  			Namespace: "claircore",
    21  			Subsystem: "indexer",
    22  			Name:      "layerscanned_total",
    23  			Help:      "Total number of database queries issued in the LayerScanned method.",
    24  		},
    25  		[]string{"query"},
    26  	)
    27  
    28  	layerScannedDuration = promauto.NewHistogramVec(
    29  		prometheus.HistogramOpts{
    30  			Namespace: "claircore",
    31  			Subsystem: "indexer",
    32  			Name:      "layerscanned_duration_seconds",
    33  			Help:      "The duration of all queries issued in the LayerScanned method",
    34  		},
    35  		[]string{"query"},
    36  	)
    37  )
    38  
    39  func (s *IndexerStore) LayerScanned(ctx context.Context, hash claircore.Digest, scnr indexer.VersionedScanner) (bool, error) {
    40  	// TODO(hank) Could this be written as a single query that reports NULL if
    41  	// the scanner isn't present?
    42  	const (
    43  		selectScanner = `
    44  SELECT
    45  	id
    46  FROM
    47  	scanner
    48  WHERE
    49  	name = $1 AND version = $2 AND kind = $3;
    50  `
    51  		selectScanned = `
    52  SELECT
    53  	EXISTS(
    54  		SELECT
    55  			1
    56  		FROM
    57  			layer
    58  			JOIN scanned_layer ON
    59  					scanned_layer.layer_id = layer.id
    60  		WHERE
    61  			layer.hash = $1
    62  			AND scanned_layer.scanner_id = $2
    63  	);
    64  `
    65  	)
    66  
    67  	start := time.Now()
    68  	var scannerID int64
    69  	err := s.pool.QueryRow(ctx, selectScanner, scnr.Name(), scnr.Version(), scnr.Kind()).
    70  		Scan(&scannerID)
    71  	switch {
    72  	case errors.Is(err, nil):
    73  	case errors.Is(err, pgx.ErrNoRows):
    74  		return false, fmt.Errorf("scanner %s not found", scnr.Name())
    75  	default:
    76  		return false, err
    77  	}
    78  	layerScannedCounter.WithLabelValues("selectScanner").Add(1)
    79  	layerScannedDuration.WithLabelValues("selectScanner").Observe(time.Since(start).Seconds())
    80  
    81  	var ok bool
    82  
    83  	start = time.Now()
    84  	err = s.pool.QueryRow(ctx, selectScanned, hash.String(), scannerID).
    85  		Scan(&ok)
    86  	if err != nil {
    87  		return false, err
    88  	}
    89  	layerScannedCounter.WithLabelValues("selectScanned").Add(1)
    90  	layerScannedDuration.WithLabelValues("selectScanned").Observe(time.Since(start).Seconds())
    91  
    92  	return ok, nil
    93  }