...
1 package cache
2
3 import (
4 "context"
5
6 "github.com/docker/distribution"
7 prometheus "github.com/docker/distribution/metrics"
8 "github.com/opencontainers/go-digest"
9 )
10
11
12
13
14 type Metrics struct {
15 Requests uint64
16 Hits uint64
17 Misses uint64
18 }
19
20
21
22
23 type Logger interface {
24 Errorf(format string, args ...interface{})
25 }
26
27
28
29 type MetricsTracker interface {
30 Hit()
31 Miss()
32 Metrics() Metrics
33 Logger(context.Context) Logger
34 }
35
36 type cachedBlobStatter struct {
37 cache distribution.BlobDescriptorService
38 backend distribution.BlobDescriptorService
39 tracker MetricsTracker
40 }
41
42 var (
43
44 cacheCount = prometheus.StorageNamespace.NewLabeledCounter("cache", "The number of cache request received", "type")
45 )
46
47
48
49 func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService) distribution.BlobDescriptorService {
50 return &cachedBlobStatter{
51 cache: cache,
52 backend: backend,
53 }
54 }
55
56
57
58 func NewCachedBlobStatterWithMetrics(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService, tracker MetricsTracker) distribution.BlobStatter {
59 return &cachedBlobStatter{
60 cache: cache,
61 backend: backend,
62 tracker: tracker,
63 }
64 }
65
66 func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
67 cacheCount.WithValues("Request").Inc(1)
68 desc, err := cbds.cache.Stat(ctx, dgst)
69 if err != nil {
70 if err != distribution.ErrBlobUnknown {
71 logErrorf(ctx, cbds.tracker, "error retrieving descriptor from cache: %v", err)
72 }
73
74 goto fallback
75 }
76 cacheCount.WithValues("Hit").Inc(1)
77 if cbds.tracker != nil {
78 cbds.tracker.Hit()
79 }
80 return desc, nil
81 fallback:
82 cacheCount.WithValues("Miss").Inc(1)
83 if cbds.tracker != nil {
84 cbds.tracker.Miss()
85 }
86 desc, err = cbds.backend.Stat(ctx, dgst)
87 if err != nil {
88 return desc, err
89 }
90
91 if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
92 logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err)
93 }
94
95 return desc, err
96
97 }
98
99 func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
100 err := cbds.cache.Clear(ctx, dgst)
101 if err != nil {
102 return err
103 }
104
105 err = cbds.backend.Clear(ctx, dgst)
106 if err != nil {
107 return err
108 }
109 return nil
110 }
111
112 func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
113 if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
114 logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err)
115 }
116 return nil
117 }
118
119 func logErrorf(ctx context.Context, tracker MetricsTracker, format string, args ...interface{}) {
120 if tracker == nil {
121 return
122 }
123
124 logger := tracker.Logger(ctx)
125 if logger == nil {
126 return
127 }
128 logger.Errorf(format, args...)
129 }
130
View as plain text