-
Notifications
You must be signed in to change notification settings - Fork 508
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
Athens: introduce Single Flight #573
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
a3e14ad
Athens: introduce singleflight
marwan-at-work fafa2bd
fix ci
marwan-at-work df8387b
small fixes
marwan-at-work c78ef03
Remove unnecessary method
marwan-at-work eec8214
simplify folder structure
marwan-at-work 9828557
dcoument stasher iface
marwan-at-work 81cd34c
fixes
marwan-at-work 6b2cc02
Fix olympus
marwan-at-work b4f9e10
Remove Version from Download Protocol
marwan-at-work d3deaee
fix olympus
marwan-at-work ed3e053
refactor fetcher
marwan-at-work 219f5cf
consolodate wrapping styles
marwan-at-work 3be9a7b
fix olympus
marwan-at-work 0e373b8
Further refactoring
marwan-at-work 578f36c
fix typo
marwan-at-work 684e101
Merge branch 'master' into sf
marwan-at-work File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package addons | ||
|
||
import ( | ||
"context" | ||
"io" | ||
|
||
"github.com/gomods/athens/pkg/download" | ||
"github.com/gomods/athens/pkg/errors" | ||
"github.com/gomods/athens/pkg/storage" | ||
) | ||
|
||
type withpool struct { | ||
dp download.Protocol | ||
|
||
// jobCh is a channel that takes an anonymous | ||
// function that it executes based on the pool's | ||
// business. The design levarages closures | ||
// so that the worker does not need to worry about | ||
// what the type of job it is taking (Info, Zip etc), | ||
// it just regulates functions and executes them | ||
// in a worker-pool fashion. | ||
jobCh chan func() | ||
} | ||
|
||
// WithPool takes a download Protocol and a number of workers | ||
// and creates a N worker pool that share all the download.Protocol | ||
// methods. | ||
func WithPool(workers int) download.Wrapper { | ||
return func(dp download.Protocol) download.Protocol { | ||
jobCh := make(chan func()) | ||
p := &withpool{dp: dp, jobCh: jobCh} | ||
|
||
p.start(workers) | ||
return p | ||
} | ||
} | ||
|
||
func (p *withpool) start(numWorkers int) { | ||
for i := 0; i < numWorkers; i++ { | ||
go p.listen() | ||
} | ||
} | ||
|
||
func (p *withpool) listen() { | ||
for f := range p.jobCh { | ||
f() | ||
} | ||
} | ||
|
||
func (p *withpool) List(ctx context.Context, mod string) ([]string, error) { | ||
const op errors.Op = "pool.List" | ||
var vers []string | ||
var err error | ||
done := make(chan struct{}, 1) | ||
p.jobCh <- func() { | ||
vers, err = p.dp.List(ctx, mod) | ||
close(done) | ||
} | ||
<-done | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
|
||
return vers, nil | ||
} | ||
|
||
func (p *withpool) Info(ctx context.Context, mod, ver string) ([]byte, error) { | ||
const op errors.Op = "pool.Info" | ||
var info []byte | ||
var err error | ||
done := make(chan struct{}, 1) | ||
p.jobCh <- func() { | ||
info, err = p.dp.Info(ctx, mod, ver) | ||
close(done) | ||
} | ||
<-done | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
return info, nil | ||
} | ||
|
||
func (p *withpool) Latest(ctx context.Context, mod string) (*storage.RevInfo, error) { | ||
const op errors.Op = "pool.Latest" | ||
var info *storage.RevInfo | ||
var err error | ||
done := make(chan struct{}, 1) | ||
p.jobCh <- func() { | ||
info, err = p.dp.Latest(ctx, mod) | ||
close(done) | ||
} | ||
<-done | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
return info, nil | ||
} | ||
|
||
func (p *withpool) GoMod(ctx context.Context, mod, ver string) ([]byte, error) { | ||
const op errors.Op = "pool.GoMod" | ||
var goMod []byte | ||
var err error | ||
done := make(chan struct{}, 1) | ||
p.jobCh <- func() { | ||
goMod, err = p.dp.GoMod(ctx, mod, ver) | ||
close(done) | ||
} | ||
<-done | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
return goMod, nil | ||
} | ||
|
||
func (p *withpool) Zip(ctx context.Context, mod, ver string) (io.ReadCloser, error) { | ||
const op errors.Op = "pool.Zip" | ||
var zip io.ReadCloser | ||
var err error | ||
done := make(chan struct{}, 1) | ||
p.jobCh <- func() { | ||
zip, err = p.dp.Zip(ctx, mod, ver) | ||
close(done) | ||
} | ||
<-done | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
return zip, nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I find it overly complicated, do you find it readable?
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.
@michalpristas I 100% agree that it's more complex. I also agree that it's less readable than what we currently have, but that comes with the complexity part.
My first option was just to lump all of this code into the
download.go
file and that would have been much much harder to read because you'd have *two worker pools and a singleflight all under the same struct. I don't mind returning to that option if you want? Otherwise, let me know if you have other ideas, totally happy to change things :)Here's what's required:
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.
I imagined something simpler e.g (and I am totally not thinking this through, just writing an idea as it goes)
map[module.v]chan
. Returns chanThere 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.
@michalpristas
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.
I dismissed my blocking review. if folks are ok with this design I will not block and will think this through if needed once I'm mentally capable of thinking.
I'm really sorry for the confusion
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.
@michalpristas no I 100% agree with you. I think we shouldn't rush this PR since it adds a lot of complexity. I'll mark this as do not merge until we have a bunch of people weighing in and maybe proposing different approaches. One idea is that I can have some of the Athens peeps at GopherCon doing a group review and brainstorm some other stuff and bringing it back here. I even don't mind opening another PR (or someone else opening another PR) that does the same thing differently so we can really compare. Thank you!
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.
Hey if you manage to get people together and brainstorm it would be great ;-)