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

     1  package postgres
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/jackc/pgx/v4/pgxpool"
     9  	"github.com/jackc/pgx/v4/stdlib"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/remind101/migrate"
    12  
    13  	"github.com/quay/claircore/datastore/postgres/migrations"
    14  	"github.com/quay/claircore/indexer"
    15  )
    16  
    17  // InitPostgresIndexerStore initialize a indexer.Store given the pgxpool.Pool
    18  func InitPostgresIndexerStore(_ context.Context, pool *pgxpool.Pool, doMigration bool) (indexer.Store, error) {
    19  	db := stdlib.OpenDB(*pool.Config().ConnConfig)
    20  	defer db.Close()
    21  
    22  	// do migrations if requested
    23  	if doMigration {
    24  		migrator := migrate.NewPostgresMigrator(db)
    25  		migrator.Table = migrations.IndexerMigrationTable
    26  		err := migrator.Exec(migrate.Up, migrations.IndexerMigrations...)
    27  		if err != nil {
    28  			return nil, fmt.Errorf("failed to perform migrations: %w", err)
    29  		}
    30  	}
    31  
    32  	store := NewIndexerStore(pool)
    33  	return store, nil
    34  }
    35  
    36  var _ indexer.Store = (*IndexerStore)(nil)
    37  
    38  // IndexerStore implements the claircore.Store interface.
    39  //
    40  // All the other exported methods live in their own files.
    41  type IndexerStore struct {
    42  	pool *pgxpool.Pool
    43  }
    44  
    45  func NewIndexerStore(pool *pgxpool.Pool) *IndexerStore {
    46  	return &IndexerStore{
    47  		pool: pool,
    48  	}
    49  }
    50  
    51  func (s *IndexerStore) Close(_ context.Context) error {
    52  	s.pool.Close()
    53  	return nil
    54  }
    55  
    56  const selectScanner = `
    57  SELECT
    58  	id
    59  FROM
    60  	scanner
    61  WHERE
    62  	name = $1 AND version = $2 AND kind = $3;
    63  `
    64  
    65  func (s *IndexerStore) selectScanners(ctx context.Context, vs indexer.VersionedScanners) ([]int64, error) {
    66  	ids := make([]int64, len(vs))
    67  	for i, v := range vs {
    68  		err := s.pool.QueryRow(ctx, selectScanner, v.Name(), v.Version(), v.Kind()).
    69  			Scan(&ids[i])
    70  		if err != nil {
    71  			return nil, fmt.Errorf("failed to retrieve id for scanner %q: %w", v.Name(), err)
    72  		}
    73  	}
    74  
    75  	return ids, nil
    76  }
    77  
    78  func promTimer(h *prometheus.HistogramVec, name string, err *error) func() time.Duration {
    79  	t := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
    80  		h.WithLabelValues(name, success(*err)).Observe(v)
    81  	}))
    82  	return t.ObserveDuration
    83  }
    84  
    85  func success(err error) string {
    86  	if err == nil {
    87  		return "true"
    88  	}
    89  	return "false"
    90  }