mirror of
https://github.com/kopia/kopia.git
synced 2026-03-12 11:16:25 -04:00
webdav: prevent webdav client race condition (#626)
The race is described in https://github.com/studio-b12/gowebdav/issues/36 We need this workaround until the fix is merged upstream, to avoid maintaining a webdav client fork. Fixes #624
This commit is contained in:
@@ -6,8 +6,13 @@
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/kopia/kopia/internal/blobtesting"
|
||||
"github.com/kopia/kopia/internal/testlogging"
|
||||
"github.com/kopia/kopia/repo/blob"
|
||||
"github.com/kopia/kopia/repo/blob/rclone"
|
||||
)
|
||||
|
||||
@@ -36,6 +41,24 @@ func TestRCloneStorage(t *testing.T) {
|
||||
|
||||
defer st.Close(ctx)
|
||||
|
||||
var eg errgroup.Group
|
||||
|
||||
// trigger multiple parallel reads to ensure we're properly preventing race
|
||||
// described in https://github.com/kopia/kopia/issues/624
|
||||
for i := 0; i < 100; i++ {
|
||||
eg.Go(func() error {
|
||||
if _, err := st.GetBlob(ctx, blob.ID(uuid.New().String()), 0, -1); !errors.Is(err, blob.ErrBlobNotFound) {
|
||||
return errors.Errorf("unexpected error when downloading non-existent blob: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := eg.Wait(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
blobtesting.VerifyStorage(ctx, t, st)
|
||||
blobtesting.AssertConnectionInfoRoundTrips(ctx, t, st)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/studio-b12/gowebdav"
|
||||
|
||||
@@ -201,7 +202,7 @@ func New(ctx context.Context, opts *Options) (blob.Storage, error) {
|
||||
cli.SetTransport(tlsutil.TransportTrustingSingleCertificate(opts.TrustedServerCertificateFingerprint))
|
||||
}
|
||||
|
||||
return &davStorage{
|
||||
s := &davStorage{
|
||||
sharded.Storage{
|
||||
Impl: &davStorageImpl{
|
||||
Options: *opts,
|
||||
@@ -211,7 +212,16 @@ func New(ctx context.Context, opts *Options) (blob.Storage, error) {
|
||||
Suffix: fsStorageChunkSuffix,
|
||||
Shards: opts.shards(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// temporary workaround to a race condition problem in https://github.com/studio-b12/gowebdav/issues/36
|
||||
// the race condition is only during first request to the server, so to fix it we force the first request
|
||||
// to read a non-existent blob, which sets the authentication method.
|
||||
if _, err := s.GetBlob(ctx, blob.ID(uuid.New().String()), 0, -1); !errors.Is(err, blob.ErrBlobNotFound) {
|
||||
return nil, errors.Errorf("unexpected error when initializing webdav: %v", err)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
Reference in New Issue
Block a user