-
Notifications
You must be signed in to change notification settings - Fork 80
/
deletemanifests.go
127 lines (119 loc) · 3.45 KB
/
deletemanifests.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package postgres
import (
"context"
"errors"
"fmt"
"github.com/jackc/pgx/v4"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/quay/zlog"
"github.com/quay/claircore"
)
var (
deleteManifestsCounter = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: "claircore",
Subsystem: "indexer",
Name: "deletemanifests_total",
Help: "Total number of calls to the DeleteManifests method.",
},
[]string{"action", "success"},
)
deleteManifestsDuration = promauto.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "claircore",
Subsystem: "indexer",
Name: "deletemanifests_duration_seconds",
Help: "The duration of taken by the DeleteManifests method.",
},
[]string{"action", "success"},
)
)
func (s *IndexerStore) DeleteManifests(ctx context.Context, ds ...claircore.Digest) ([]claircore.Digest, error) {
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/DeleteManifests")
const (
getManifestID = `SELECT id FROM manifest WHERE hash = $1`
getLayers = `SELECT layer_id FROM manifest_layer WHERE manifest_id = $1;`
deleteManifest = `DELETE FROM manifest WHERE id = $1;`
deleteLayers = `DELETE FROM
layer
WHERE
id IN (
SELECT
l.id
FROM
layer l
LEFT JOIN manifest_layer ml ON l.id = ml.layer_id
WHERE
l.id = $1
AND ml.layer_id IS NULL
);`
)
var err error
defer promTimer(deleteManifestsDuration, "deleteManifest", &err)()
defer func(e *error) {
deleteManifestsCounter.WithLabelValues("deleteManifest", success(*e)).Inc()
}(&err)
deletedManifests := make([]claircore.Digest, 0, len(ds))
for _, d := range ds {
s.pool.BeginFunc(ctx, func(tx pgx.Tx) error {
defer promTimer(deleteManifestsDuration, "deleteLayers", &err)()
defer func(e *error) {
deleteManifestsCounter.WithLabelValues("deleteLayers", success(*e)).Inc()
}(&err)
// Get manifest ID
var manifestID int64
err := tx.QueryRow(ctx, getManifestID, d).Scan(&manifestID)
switch {
case errors.Is(err, nil):
case errors.Is(err, pgx.ErrNoRows):
// Currently a silent error, go on to the next
return nil
default:
return fmt.Errorf("unable query manifest: %w", err)
}
// Get all layer IDs
lRows, err := tx.Query(ctx, getLayers, manifestID)
if err != nil {
return fmt.Errorf("unable to query layers: %w", err)
}
defer lRows.Close()
lIDs := []int64{}
for lRows.Next() {
var layerID int64
err = lRows.Scan(&layerID)
if err != nil {
return fmt.Errorf("unable to scan layer ID: %w", err)
}
lIDs = append(lIDs, layerID)
}
if err := lRows.Err(); err != nil {
return fmt.Errorf("error reading layer data: %w", err)
}
// Delete manifest
_, err = tx.Exec(ctx, deleteManifest, manifestID)
if err != nil {
return fmt.Errorf("unable to delete manifest: %w", err)
}
// Delete eligible layers
for _, lID := range lIDs {
tag, err := tx.Exec(ctx, deleteLayers, lID)
if err != nil {
return fmt.Errorf("unable check layer usage: %w", err)
}
ra := tag.RowsAffected()
zlog.Debug(ctx).
Int64("count", ra).
Str("manifest", d.String()).
Msg("deleted layers for manifest")
}
deletedManifests = append(deletedManifests, d)
return nil
})
}
zlog.Debug(ctx).
Int("count", len(deletedManifests)).
Int("nonexistant", len(ds)-len(deletedManifests)).
Msg("deleted manifests")
return deletedManifests, nil
}