Merge pull request #11457 from jsternberg/backport-remote-write-grpc-limits-exceeded
[release/2.0] Update remote content to break up writes to avoid grpc message size limits
This commit is contained in:
commit
84e6cbafd5
@ -26,6 +26,7 @@ import (
|
|||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
|
||||||
"github.com/containerd/containerd/v2/core/content"
|
"github.com/containerd/containerd/v2/core/content"
|
||||||
|
"github.com/containerd/containerd/v2/defaults"
|
||||||
"github.com/containerd/containerd/v2/pkg/protobuf"
|
"github.com/containerd/containerd/v2/pkg/protobuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,27 +77,37 @@ func (rw *remoteWriter) Digest() digest.Digest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
||||||
|
const maxBufferSize = defaults.DefaultMaxSendMsgSize >> 1
|
||||||
|
for i := 0; i < len(p); i += maxBufferSize {
|
||||||
offset := rw.offset
|
offset := rw.offset
|
||||||
|
|
||||||
|
end := i + maxBufferSize
|
||||||
|
if end > len(p) {
|
||||||
|
end = len(p)
|
||||||
|
}
|
||||||
|
data := p[i:end]
|
||||||
|
|
||||||
resp, err := rw.send(&contentapi.WriteContentRequest{
|
resp, err := rw.send(&contentapi.WriteContentRequest{
|
||||||
Action: contentapi.WriteAction_WRITE,
|
Action: contentapi.WriteAction_WRITE,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
Data: p,
|
Data: data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to send write: %w", errgrpc.ToNative(err))
|
return 0, fmt.Errorf("failed to send write: %w", errgrpc.ToNative(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
n = int(resp.Offset - offset)
|
written := int(resp.Offset - offset)
|
||||||
if n < len(p) {
|
rw.offset += int64(written)
|
||||||
err = io.ErrShortWrite
|
|
||||||
}
|
|
||||||
|
|
||||||
rw.offset += int64(n)
|
|
||||||
if resp.Digest != "" {
|
if resp.Digest != "" {
|
||||||
rw.digest = digest.Digest(resp.Digest)
|
rw.digest = digest.Digest(resp.Digest)
|
||||||
}
|
}
|
||||||
return
|
n += written
|
||||||
|
|
||||||
|
if written < len(data) {
|
||||||
|
return n, io.ErrShortWrite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) {
|
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) {
|
||||||
|
@ -175,6 +175,13 @@ func checkContentStoreWriter(ctx context.Context, t *testing.T, cs content.Store
|
|||||||
}
|
}
|
||||||
defer w4.Close()
|
defer w4.Close()
|
||||||
|
|
||||||
|
c5, d5 := createContent(16 << 21)
|
||||||
|
w5, err := content.OpenWriter(ctx, cs, content.WithRef("c5"), content.WithDescriptor(ocispec.Descriptor{Size: int64(len(c5)), Digest: d5}))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer w5.Close()
|
||||||
|
|
||||||
smallbuf := make([]byte, 32)
|
smallbuf := make([]byte, 32)
|
||||||
for _, s := range []struct {
|
for _, s := range []struct {
|
||||||
content []byte
|
content []byte
|
||||||
@ -201,6 +208,11 @@ func checkContentStoreWriter(ctx context.Context, t *testing.T, cs content.Store
|
|||||||
digest: d4,
|
digest: d4,
|
||||||
writer: w4,
|
writer: w4,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
content: c5,
|
||||||
|
digest: d5,
|
||||||
|
writer: w5,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
n, err := io.CopyBuffer(s.writer, bytes.NewReader(s.content), smallbuf)
|
n, err := io.CopyBuffer(s.writer, bytes.NewReader(s.content), smallbuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -647,7 +659,6 @@ func checkLabels(ctx context.Context, t *testing.T, cs content.Store) {
|
|||||||
if err := checkInfo(ctx, cs, d1, info, preCommit, postCommit, preUpdate, postUpdate); err != nil {
|
if err := checkInfo(ctx, cs, d1, info, preCommit, postCommit, preUpdate, postUpdate); err != nil {
|
||||||
t.Fatalf("Check info failed: %+v", err)
|
t.Fatalf("Check info failed: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkResume(rf func(context.Context, content.Writer, []byte, int64, int64, digest.Digest) error) func(ctx context.Context, t *testing.T, cs content.Store) {
|
func checkResume(rf func(context.Context, content.Writer, []byte, int64, int64, digest.Digest) error) func(ctx context.Context, t *testing.T, cs content.Store) {
|
||||||
@ -734,7 +745,6 @@ func resumeDiscard(ctx context.Context, w content.Writer, b []byte, written, siz
|
|||||||
}
|
}
|
||||||
if err := w.Commit(ctx, size, dgst); err != nil {
|
if err := w.Commit(ctx, size, dgst); err != nil {
|
||||||
return fmt.Errorf("commit failed: %w", err)
|
return fmt.Errorf("commit failed: %w", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -931,7 +941,6 @@ func checkCrossNSAppend(ctx context.Context, t *testing.T, cs content.Store) {
|
|||||||
if err := checkContent(ctx2, cs, d2, info2, t1, t3, t1, t3); err != nil {
|
if err := checkContent(ctx2, cs, d2, info2, t1, t3, t1, t3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCrossNSIsolate(ctx context.Context, t *testing.T, cs content.Store) {
|
func checkCrossNSIsolate(ctx context.Context, t *testing.T, cs content.Store) {
|
||||||
@ -1129,6 +1138,7 @@ func checkInfo(ctx context.Context, cs content.Store, d digest.Digest, expected
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkContent(ctx context.Context, cs content.Store, d digest.Digest, expected content.Info, c1, c2, u1, u2 time.Time) error {
|
func checkContent(ctx context.Context, cs content.Store, d digest.Digest, expected content.Info, c1, c2, u1, u2 time.Time) error {
|
||||||
if err := checkInfo(ctx, cs, d, expected, c1, c2, u1, u2); err != nil {
|
if err := checkInfo(ctx, cs, d, expected, c1, c2, u1, u2); err != nil {
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user