Description
See e.g.
go-containerregistry/pkg/v1/remote/puller.go
Lines 65 to 90 in c4dd792
(same issue is in the Pusher)
For the code like:
puller := remote.NewPuller() // cache the puller instance
// somewhere later
puller.Head(ctx, reference)
In this flow, fetcher is created lazily on access, but it uses the ctx
passed with the first request. If the fetcher fails to init itself because ctx
got canceled, it will be cached forever in the failed state (due to sync.Once
). While the next .Head
request might come with non-canceled context, it will still fail with the first error.
Moreover, the ctx
used to initialize the fetcher is same as ctx
used for the Head
request itself, so passing context.Background
is not an option.
There is no interface to clean cached fetcher, or even skip the cache.
Is it by design?
The only workaround is to create Puller
/Pusher
on each request, which completely cancels the idea of caching/reusing fetchers.