From 1d0c75b0c2b0f825b430d61743f25e9b66a674d6 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 2 Nov 2022 10:27:31 +0000 Subject: [PATCH] ftp: retry errors when initiating downloads This adds a retry loop to the Open() call in the FTP server so it can retry failures opening files. This should make downloading multipart files more reliable. See: https://forum.rclone.org/t/downloads-fail-from-remote-server-error-426-failure-writing-network-stream/33839/ --- backend/ftp/ftp.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/ftp/ftp.go b/backend/ftp/ftp.go index 6ebafb344..8dd520efb 100644 --- a/backend/ftp/ftp.go +++ b/backend/ftp/ftp.go @@ -1194,15 +1194,26 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (rc io.Read } } } - c, err := o.fs.getFtpConnection(ctx) + + var ( + fd *ftp.Response + c *ftp.ServerConn + ) + err = o.fs.pacer.Call(func() (bool, error) { + c, err = o.fs.getFtpConnection(ctx) + if err != nil { + return false, err // getFtpConnection has retries already + } + fd, err = c.RetrFrom(o.fs.opt.Enc.FromStandardPath(path), uint64(offset)) + if err != nil { + o.fs.putFtpConnection(&c, err) + } + return shouldRetry(ctx, err) + }) if err != nil { return nil, fmt.Errorf("open: %w", err) } - fd, err := c.RetrFrom(o.fs.opt.Enc.FromStandardPath(path), uint64(offset)) - if err != nil { - o.fs.putFtpConnection(&c, err) - return nil, fmt.Errorf("open: %w", err) - } + rc = &ftpReadCloser{rc: readers.NewLimitedReadCloser(fd, limit), c: c, f: o.fs} return rc, nil }