Add resumable downloads, download paths, queue controls and history
This commit is contained in:
1 parent
434f6441da
commit
6027cfabb9
43 files changed
+2138
-291
No files matched your search
@@ -0,0 +1,55 @@
|
||||
package fetch
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
bufferSize = 1 << 20
|
||||
stallTimeout = 2 * time.Minute
|
||||
)
|
||||
|
||||
func copyBody(destination io.Writer, body io.ReadCloser, remaining int64, record func(int64) error) error {
|
||||
var stalled atomic.Bool
|
||||
stallTimer := time.AfterFunc(stallTimeout, func() {
|
||||
stalled.Store(true)
|
||||
body.Close()
|
||||
})
|
||||
defer stallTimer.Stop()
|
||||
|
||||
buffer := make([]byte, bufferSize)
|
||||
for remaining != 0 {
|
||||
readSize := len(buffer)
|
||||
if remaining > 0 && remaining < int64(readSize) {
|
||||
readSize = int(remaining)
|
||||
}
|
||||
|
||||
count, readErr := body.Read(buffer[:readSize])
|
||||
if count > 0 {
|
||||
stallTimer.Reset(stallTimeout)
|
||||
if _, err := destination.Write(buffer[:count]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := record(int64(count)); err != nil {
|
||||
return err
|
||||
}
|
||||
if remaining > 0 {
|
||||
remaining -= int64(count)
|
||||
}
|
||||
}
|
||||
if errors.Is(readErr, io.EOF) {
|
||||
return nil
|
||||
}
|
||||
if readErr != nil {
|
||||
if stalled.Load() {
|
||||
return ErrStalled
|
||||
}
|
||||
return fmt.Errorf("%w: %w", errConnectionFailed, readErr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user