Improve push handler ordering

Allow manifest uploads to happen in parallel and defer
manifest list and index until end.

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2022-09-13 22:08:12 -07:00
parent 737257bb48
commit 9ae92f16e0
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB

View File

@ -201,14 +201,19 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error { func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
var m sync.Mutex var m sync.Mutex
manifestStack := []ocispec.Descriptor{} manifests := []ocispec.Descriptor{}
indexStack := []ocispec.Descriptor{}
filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
switch desc.MediaType { switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest, case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
m.Lock() m.Lock()
manifestStack = append(manifestStack, desc) manifests = append(manifests, desc)
m.Unlock()
return nil, images.ErrStopHandler
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
m.Lock()
indexStack = append(indexStack, desc)
m.Unlock() m.Unlock()
return nil, images.ErrStopHandler return nil, images.ErrStopHandler
default: default:
@ -235,16 +240,18 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
return err return err
} }
if err := images.Dispatch(ctx, pushHandler, limiter, manifests...); err != nil {
return err
}
// Iterate in reverse order as seen, parent always uploaded after child // Iterate in reverse order as seen, parent always uploaded after child
for i := len(manifestStack) - 1; i >= 0; i-- { for i := len(indexStack) - 1; i >= 0; i-- {
_, err := pushHandler(ctx, manifestStack[i]) err := images.Dispatch(ctx, pushHandler, limiter, indexStack[i])
if err != nil { if err != nil {
// TODO(estesp): until we have a more complete method for index push, we need to report // TODO(estesp): until we have a more complete method for index push, we need to report
// missing dependencies in an index/manifest list by sensing the "400 Bad Request" // missing dependencies in an index/manifest list by sensing the "400 Bad Request"
// as a marker for this problem // as a marker for this problem
if (manifestStack[i].MediaType == ocispec.MediaTypeImageIndex || if errors.Unwrap(err) != nil && strings.Contains(errors.Unwrap(err).Error(), "400 Bad Request") {
manifestStack[i].MediaType == images.MediaTypeDockerSchema2ManifestList) &&
errors.Unwrap(err) != nil && strings.Contains(errors.Unwrap(err).Error(), "400 Bad Request") {
return fmt.Errorf("manifest list/index references to blobs and/or manifests are missing in your target registry: %w", err) return fmt.Errorf("manifest list/index references to blobs and/or manifests are missing in your target registry: %w", err)
} }
return err return err