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 }