Skip to content

Commit

Permalink
copy: remove max number of ErrResets
Browse files Browse the repository at this point in the history
If a writer continually asks to be reset then it should always succeed -
it should be the responsibility of the underlying content.Writer to
stop producing ErrReset after some amount of time and to instead return
the underlying issue - which pushWriter already does today, using the
doWithRetries function.

doWithRetries already has a separate cap for retries of 6 requests (5
retries after the original failure), and it seems like this would be
previously overridden by content.Copy's max number of 5 attempts, hiding
the original error.

Signed-off-by: Justin Chadwell <me@jedevc.com>
  • Loading branch information
jedevc committed Mar 4, 2024
1 parent 0465472 commit a800400
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
8 changes: 1 addition & 7 deletions content/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// maxResets is the no.of times the Copy() method can tolerate a reset of the body
const maxResets = 5

var ErrReset = errors.New("writer has been reset")

var bufPool = sync.Pool{
Expand Down Expand Up @@ -160,7 +157,7 @@ func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected dig
}
}

for i := 0; i < maxResets; i++ {
for i := 0; ; i++ {
if i >= 1 {
log.G(ctx).WithField("digest", expected).Debugf("retrying copy due to reset")
}
Expand Down Expand Up @@ -201,9 +198,6 @@ func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected dig
}
return nil
}

log.G(ctx).WithField("digest", expected).Errorf("failed to copy after %d retries", maxResets)
return fmt.Errorf("failed to copy after %d retries", maxResets)
}

// CopyReaderAt copies to a writer from a given reader at for the given
Expand Down
43 changes: 36 additions & 7 deletions content/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"bytes"
"context"
_ "crypto/sha256" // required by go-digest
"fmt"
"errors"
"io"
"strings"
"testing"
Expand All @@ -42,7 +42,7 @@ func TestCopy(t *testing.T) {
cf1 := func(buf *bytes.Buffer, st Status) commitFunction {
i := 0
return func() error {
// function resets the first time
// function resets the first time, but then succeeds after
if i == 0 {
// this is the case where, the pipewriter to which the data was being written has
// changed. which means we need to clear the buffer
Expand All @@ -55,11 +55,28 @@ func TestCopy(t *testing.T) {
}
}

cf2err := errors.New("commit failed")
cf2 := func(buf *bytes.Buffer, st Status) commitFunction {
i := 0
return func() error {
// function resets for more than the maxReset value
if i < maxResets+1 {
// function resets a lot of times, and eventually fails
if i < 10 {
// this is the case where, the pipewriter to which the data was being written has
// changed. which means we need to clear the buffer
i++
buf.Reset()
st.Offset = 0
return ErrReset
}
return cf2err
}
}

cf3 := func(buf *bytes.Buffer, st Status) commitFunction {
i := 0
return func() error {
// function resets a lot of times, and eventually succeeds
if i < 10 {
// this is the case where, the pipewriter to which the data was being written has
// changed. which means we need to clear the buffer
i++
Expand All @@ -73,8 +90,10 @@ func TestCopy(t *testing.T) {

s1 := Status{}
s2 := Status{}
s3 := Status{}
b1 := bytes.Buffer{}
b2 := bytes.Buffer{}
b3 := bytes.Buffer{}

var testcases = []struct {
name string
Expand Down Expand Up @@ -130,15 +149,25 @@ func TestCopy(t *testing.T) {
expected: "content to copy",
},
{
name: "write fails more than maxReset times due to reset",
name: "write fails after lots of resets",
source: newCopySource("content to copy"),
writer: fakeWriter{
Buffer: &b2,
status: s2,
commitFunc: cf2(&b2, s2),
},
expected: "",
expectedErr: fmt.Errorf("failed to copy after %d retries", maxResets),
expectedErr: cf2err,
},
{
name: "write succeeds after lots of resets",
source: newCopySource("content to copy"),
writer: fakeWriter{
Buffer: &b3,
status: s3,
commitFunc: cf3(&b3, s3),
},
expected: "content to copy",
},
}

Expand All @@ -153,7 +182,7 @@ func TestCopy(t *testing.T) {

// if an error is expected then further comparisons are not required
if testcase.expectedErr != nil {
assert.Equal(t, testcase.expectedErr, err)
assert.ErrorIs(t, err, testcase.expectedErr)
return
}

Expand Down

0 comments on commit a800400

Please sign in to comment.