github.com/quay/claircore@v1.5.28/datastore/postgres/persistmanifest.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  )
    13  
    14  var (
    15  	persistManifestCounter = promauto.NewCounterVec(
    16  		prometheus.CounterOpts{
    17  			Namespace: "claircore",
    18  			Subsystem: "indexer",
    19  			Name:      "persistmanifest_total",
    20  			Help:      "Total number of database queries issued in the PersistManifest method.",
    21  		},
    22  		[]string{"query"},
    23  	)
    24  
    25  	persistManifestDuration = promauto.NewHistogramVec(
    26  		prometheus.HistogramOpts{
    27  			Namespace: "claircore",
    28  			Subsystem: "indexer",
    29  			Name:      "persistmanifest_duration_seconds",
    30  			Help:      "The duration of all queries issued in the PersistManifest method",
    31  		},
    32  		[]string{"query"},
    33  	)
    34  )
    35  
    36  func (s *IndexerStore) PersistManifest(ctx context.Context, manifest claircore.Manifest) error {
    37  	const (
    38  		insertManifest = `
    39  		INSERT INTO manifest (hash)
    40  		VALUES ($1)
    41  		ON CONFLICT DO NOTHING;
    42  		`
    43  		insertLayer = `
    44  		INSERT INTO layer (hash)
    45  		VALUES ($1)
    46  		ON CONFLICT DO NOTHING;
    47  		`
    48  		insertManifestLayer = `
    49  		WITH manifests AS (
    50  			SELECT id AS manifest_id
    51  			FROM manifest
    52  			WHERE hash = $1
    53  		),
    54  			 layers AS (
    55  				 SELECT id AS layer_id
    56  				 FROM layer
    57  				 WHERE hash = $2
    58  			 )
    59  		INSERT
    60  		INTO manifest_layer (manifest_id, layer_id, i)
    61  		VALUES ((SELECT manifest_id FROM manifests),
    62  				(SELECT layer_id FROM layers),
    63  				$3)
    64  		ON CONFLICT DO NOTHING;
    65  		`
    66  	)
    67  
    68  	tx, err := s.pool.Begin(ctx)
    69  	if err != nil {
    70  		return fmt.Errorf("failed to create transaction: %w", err)
    71  	}
    72  	defer tx.Rollback(ctx)
    73  
    74  	start := time.Now()
    75  	_, err = tx.Exec(ctx, insertManifest, manifest.Hash)
    76  	if err != nil {
    77  		return fmt.Errorf("failed to insert manifest: %w", err)
    78  	}
    79  	persistManifestCounter.WithLabelValues("insertManifest").Add(1)
    80  	persistManifestDuration.WithLabelValues("insertManifest").Observe(time.Since(start).Seconds())
    81  
    82  	for i, layer := range manifest.Layers {
    83  		start := time.Now()
    84  		_, err = tx.Exec(ctx, insertLayer, layer.Hash)
    85  		if err != nil {
    86  			return fmt.Errorf("failed to insert layer: %w", err)
    87  		}
    88  		persistManifestCounter.WithLabelValues("insertLayer").Add(1)
    89  		persistManifestDuration.WithLabelValues("insertLayer").Observe(time.Since(start).Seconds())
    90  
    91  		start = time.Now()
    92  		_, err = tx.Exec(ctx, insertManifestLayer, manifest.Hash, layer.Hash, i)
    93  		if err != nil {
    94  			return fmt.Errorf("failed to insert manifest -> layer link: %w", err)
    95  		}
    96  		persistManifestCounter.WithLabelValues("insertManifestLayer").Add(1)
    97  		persistManifestDuration.WithLabelValues("insertManifestLayer").Observe(time.Since(start).Seconds())
    98  	}
    99  
   100  	err = tx.Commit(ctx)
   101  	if err != nil {
   102  		return fmt.Errorf("failed to commit tx: %w", err)
   103  	}
   104  	return nil
   105  }