New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
150 parallel pull #352
150 parallel pull #352
Changes from 3 commits
1793117
e520b04
b4843ae
f9f9520
379df01
0773ac0
e3ebe6b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,19 +144,49 @@ func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.A | |
return err | ||
} | ||
// FIXME: Try to stream the images? | ||
// FIXME: Lunch the getRemoteImage() in goroutines | ||
|
||
idChan := make(chan string, len(history)) | ||
|
||
for _, j := range history { | ||
if !graph.Exists(j.Id) { | ||
img, layer, err := graph.getRemoteImage(stdout, j.Id, authConfig) | ||
if err != nil { | ||
// FIXME: Keep goging in case of error? | ||
return err | ||
if !graph.Exists(j.Id){ | ||
idChan <- j.Id | ||
} | ||
} | ||
|
||
expectedResponseCount := len(idChan) | ||
errChan := make(chan error) | ||
maxWorkers := 4 | ||
|
||
for i := 0; i < maxWorkers; i++ { | ||
go func () { | ||
for len(idChan) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is racy. Another worker could pop the last item off the channel in the meantime. The fix is to do something like go func() {
for id := range c {
img, layer, err := graph.getRemoteImage(stdout, <-idChan, authConfig)
// ...
}
}() |
||
img, layer, err := graph.getRemoteImage(stdout, <-idChan, authConfig) | ||
if err != nil { | ||
errChan <- err | ||
continue | ||
} | ||
if err = graph.Register(layer, img); err != nil { | ||
errChan <- err | ||
continue | ||
} | ||
errChan <- nil | ||
} | ||
if err = graph.Register(layer, img); err != nil { | ||
return err | ||
}() | ||
} | ||
|
||
var errMsg error | ||
|
||
for i := 0; i < expectedResponseCount; i++ { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't you range over There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. I'd have to close the channel from one of the goroutines, and I can't tell if another is still in progress. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah sorry, I didn't read this closely enough. My mistake. |
||
if err = <- errChan; err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please make sure you've gofmted your changes (you can use |
||
if errMsg == nil { | ||
errMsg = fmt.Errorf("The following errors were encountered while downloading images:\n") | ||
} | ||
errMsg = fmt.Errorf("%s\n%s",errMsg, err) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a simple []string and strings.Join would be nicer here? You wouldn't allocate as many new strings, you wouldn't have the overhead of reflection and the code would be more straightforward to understand, by not having the "is it initialized yet?" check on every iteration. errors := []string{"The following errors..."}
for ... {
// append if error
}
if len(errors) > 1 {
return errors.New(strings.Join(errors, "\n"))
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. Updated |
||
} | ||
if errMsg != nil { | ||
return errMsg | ||
} | ||
return nil | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of limiting the number of workers to 4? Spawning a whole bunch of goroutines is fine. Maybe you're trying to limit the number of concurrent HTTP requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's to limit the number of concurrent requests.