Skip to content

Commit e674f5b

Browse files
authored
Fix the ui progress panic with multiple threads (#99)
* Fix the ui progress panic with multiple threads * Close the ui process when it is done * Fix the process close issues * Avoid using a global uiprogress instead of a new * Add comments
1 parent fddb270 commit e674f5b

File tree

3 files changed

+45
-20
lines changed

3 files changed

+45
-20
lines changed

pkg/http.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ func DownloadFileWithMultipleThreadKeepParts(targetURL, targetFilePath string, t
4343

4444
// DownloadWithContinue downloads the files continuously
4545
func DownloadWithContinue(targetURL, output string, index, continueAt, end int64, showProgress bool) (err error) {
46-
return net.DownloadWithContinue(targetURL, output, index, continueAt, end, showProgress)
46+
downloader := &net.ContinueDownloader{}
47+
return downloader.DownloadWithContinue(targetURL, output, index, continueAt, end, showProgress)
4748
}
4849

4950
// DetectSize returns the size of target resource

pkg/net/http.go

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ type HTTPDownloader struct {
4545
Timeout int
4646
MaxAttempts int
4747

48-
Debug bool
49-
RoundTripper http.RoundTripper
48+
Debug bool
49+
RoundTripper http.RoundTripper
50+
progressIndicator *ProgressIndicator
5051
}
5152

5253
// SetProxy set the proxy for a http
@@ -153,14 +154,14 @@ func (h *HTTPDownloader) DownloadFile() error {
153154
if h.Title == "" {
154155
h.Title = "Downloading"
155156
}
156-
writer := &ProgressIndicator{
157+
h.progressIndicator = &ProgressIndicator{
157158
Title: h.Title,
158159
}
159160
if showProgress {
160161
if total, ok := resp.Header["Content-Length"]; ok && len(total) > 0 {
161162
fileLength, err := strconv.ParseInt(total[0], 10, 64)
162163
if err == nil {
163-
writer.Total = float64(fileLength)
164+
h.progressIndicator.Total = float64(fileLength)
164165
}
165166
}
166167
}
@@ -176,14 +177,14 @@ func (h *HTTPDownloader) DownloadFile() error {
176177
return err
177178
}
178179

179-
writer.Writer = out
180+
h.progressIndicator.Writer = out
180181

181182
if showProgress {
182-
writer.Init()
183+
h.progressIndicator.Init()
183184
}
184185

185186
// Write the body to file
186-
_, err = io.Copy(writer, resp.Body)
187+
_, err = io.Copy(h.progressIndicator, resp.Body)
187188
return err
188189
}
189190

@@ -219,13 +220,16 @@ func DownloadFileWithMultipleThreadKeepParts(targetURL, targetFilePath string, t
219220
}
220221
start := unit * int64(index)
221222

222-
if downloadErr := DownloadWithContinue(targetURL, fmt.Sprintf("%s-%d", targetFilePath, index), int64(index), start, end, showProgress); downloadErr != nil {
223+
downloader := &ContinueDownloader{}
224+
if downloadErr := downloader.DownloadWithContinue(targetURL, fmt.Sprintf("%s-%d", targetFilePath, index),
225+
int64(index), start, end, showProgress); downloadErr != nil {
223226
fmt.Println(downloadErr)
224227
}
225228
}(i, &wg)
226229
}
227230

228231
wg.Wait()
232+
ProgressIndicator{}.Close()
229233

230234
// concat all these partial files
231235
var f *os.File
@@ -251,33 +255,39 @@ func DownloadFileWithMultipleThreadKeepParts(targetURL, targetFilePath string, t
251255
}
252256
} else {
253257
fmt.Println("cannot download it using multiple threads, failed to one")
254-
err = DownloadWithContinue(targetURL, targetFilePath, -1, 0, 0, true)
258+
downloader := &ContinueDownloader{}
259+
err = downloader.DownloadWithContinue(targetURL, targetFilePath, -1, 0, 0, true)
255260
}
256261
return
257262
}
258263

264+
// ContinueDownloader is a downloader which support continuously download
265+
type ContinueDownloader struct {
266+
downloader *HTTPDownloader
267+
}
268+
259269
// DownloadWithContinue downloads the files continuously
260-
func DownloadWithContinue(targetURL, output string, index, continueAt, end int64, showProgress bool) (err error) {
261-
downloader := HTTPDownloader{
270+
func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, index, continueAt, end int64, showProgress bool) (err error) {
271+
c.downloader = &HTTPDownloader{
262272
TargetFilePath: output,
263273
URL: targetURL,
264274
ShowProgress: showProgress,
265275
}
266276
if index >= 0 {
267-
downloader.Title = fmt.Sprintf("Downloading part %d", index)
277+
c.downloader.Title = fmt.Sprintf("Downloading part %d", index)
268278
}
269279

270280
if continueAt >= 0 {
271-
downloader.Header = make(map[string]string, 1)
281+
c.downloader.Header = make(map[string]string, 1)
272282

273283
if end > continueAt {
274-
downloader.Header["Range"] = fmt.Sprintf("bytes=%d-%d", continueAt, end)
284+
c.downloader.Header["Range"] = fmt.Sprintf("bytes=%d-%d", continueAt, end)
275285
} else {
276-
downloader.Header["Range"] = fmt.Sprintf("bytes=%d-", continueAt)
286+
c.downloader.Header["Range"] = fmt.Sprintf("bytes=%d-", continueAt)
277287
}
278288
}
279289

280-
if err = downloader.DownloadFile(); err != nil {
290+
if err = c.downloader.DownloadFile(); err != nil {
281291
err = fmt.Errorf("cannot download from %s, error: %v", targetURL, err)
282292
}
283293
return

pkg/net/progress.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,20 @@ type ProgressIndicator struct {
1818
bar *uiprogress.Bar
1919
}
2020

21+
var process *uiprogress.Progress
22+
2123
// Init set the default value for progress indicator
2224
func (i *ProgressIndicator) Init() {
23-
uiprogress.Start() // start rendering
24-
i.bar = uiprogress.AddBar(100) // Add a new bar
25+
// start rendering
26+
if process == nil {
27+
process = uiprogress.New()
28+
process.Start()
29+
}
30+
i.bar = process.AddBar(100) // Add a new bar
2531

2632
// optionally, append and prepend completion and elapsed time
2733
i.bar.AppendCompleted()
28-
// i.bar.PrependElapsed()
34+
//i.bar.PrependElapsed()
2935

3036
if i.Title != "" {
3137
i.bar.PrependFunc(func(_ *uiprogress.Bar) string {
@@ -34,6 +40,14 @@ func (i *ProgressIndicator) Init() {
3440
}
3541
}
3642

43+
// Close shutdowns the ui process
44+
func (i ProgressIndicator) Close() {
45+
if process != nil {
46+
process.Stop()
47+
process = nil
48+
}
49+
}
50+
3751
// Write writes the progress
3852
func (i *ProgressIndicator) Write(p []byte) (n int, err error) {
3953
n, err = i.Writer.Write(p)

0 commit comments

Comments
 (0)