Skip to content

Commit 05d9b2e

Browse files
committed
Implement Resolve{Manifest,Tag,Blob} in our registry cache
Now that we have `Descriptor` objects (and a way to cache them), this implementation is trivial. 🎉
1 parent 7cf25c6 commit 05d9b2e

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

registry/cache.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,73 @@ func (rc *registryCache) GetTag(ctx context.Context, repo string, tag string) (o
134134
return ocimem.NewBytesReader(desc.Data, desc), nil
135135
}
136136

137+
func (rc *registryCache) resolveBlob(ctx context.Context, repo string, digest ociregistry.Digest, f func(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.Descriptor, error)) (ociregistry.Descriptor, error) {
138+
rc.mu.Lock()
139+
defer rc.mu.Unlock()
140+
141+
if desc, ok := rc.data[digest]; ok && rc.has[cacheKeyDigest(repo, digest)] {
142+
return desc, nil
143+
}
144+
145+
desc, err := f(ctx, repo, digest)
146+
if err != nil {
147+
return desc, err
148+
}
149+
150+
digest = desc.Digest // if this isn't a no-op, we've got a naughty registry
151+
152+
rc.has[cacheKeyDigest(repo, digest)] = true
153+
154+
// carefully copy only valid Resolve* fields such that any other existing fields are kept (this matters more if we ever make our mutexes better/less aggressive 👀)
155+
if d, ok := rc.data[digest]; ok {
156+
d.MediaType = desc.MediaType
157+
d.Digest = desc.Digest
158+
d.Size = desc.Size
159+
desc = d
160+
}
161+
rc.data[digest] = desc
162+
163+
return desc, nil
164+
}
165+
166+
func (rc *registryCache) ResolveManifest(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
167+
return rc.resolveBlob(ctx, repo, digest, rc.registry.ResolveManifest)
168+
}
169+
170+
func (rc *registryCache) ResolveBlob(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
171+
return rc.resolveBlob(ctx, repo, digest, rc.registry.ResolveBlob)
172+
}
173+
174+
func (rc *registryCache) ResolveTag(ctx context.Context, repo string, tag string) (ociregistry.Descriptor, error) {
175+
rc.mu.Lock()
176+
defer rc.mu.Unlock()
177+
178+
tagKey := cacheKeyTag(repo, tag)
179+
180+
if digest, ok := rc.tags[tagKey]; ok {
181+
if desc, ok := rc.data[digest]; ok {
182+
return desc, nil
183+
}
184+
}
185+
186+
desc, err := rc.registry.ResolveTag(ctx, repo, tag)
187+
if err != nil {
188+
return desc, err
189+
}
190+
191+
rc.has[cacheKeyDigest(repo, desc.Digest)] = true
192+
rc.tags[tagKey] = desc.Digest
193+
194+
// carefully copy only valid Resolve* fields such that any other existing fields are kept (this matters more if we ever make our mutexes better/less aggressive 👀)
195+
if d, ok := rc.data[desc.Digest]; ok {
196+
d.MediaType = desc.MediaType
197+
d.Digest = desc.Digest
198+
d.Size = desc.Size
199+
desc = d
200+
}
201+
rc.data[desc.Digest] = desc
202+
203+
return desc, nil
204+
}
205+
137206
// TODO more methods (currently only implements what's actually necessary for SynthesizeIndex)

0 commit comments

Comments
 (0)