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 }