@@ -35,28 +35,35 @@ func newPackageCache(fetcher Fetcher) *packageCache {
3535// This will block until the sources are available.
3636// If the sources are cached, then this will be fast,
3737// otherwise it will await a network request before returning.
38+ //
39+ // Since GET http requests do not deduplicate requests for the same
40+ // package file and we could get duplicate requests because of diamond
41+ // dependencies (more than one package imports the same package),
42+ // this load will deduplicate requests. Multiple requests to the same
43+ // import path will create only one network request but will block
44+ // all the `Load` calls for that import path until the package has been loaded.
3845func (pc * packageCache ) Load (importPath string ) (* sources.Sources , loadResult , error ) {
39- load := pc .getLoadStratagy (importPath )
46+ load := pc .getLoadStrategy (importPath )
4047
4148 srcs := & sources.Sources {}
4249 result , err := load (srcs )
4350 return srcs , result , err
4451}
4552
46- // loadStrategy is the stratagy for performing the load based
53+ // loadStrategy is the strategy for performing the load based
4754// on the current state of any other load of the same package.
4855//
4956// If this returns loadFailed, the error will be non-nil.
5057// and if the error is non-nil, the loadResult will be loadFailed.
5158type loadStrategy func (srcs * sources.Sources ) (loadResult , error )
5259
53- // getLoadStratagy returns the stratagy to complete loading the package.
54- // When the returned stratagy is run, it may either return the cached
60+ // getLoadStrategy returns the strategy to complete loading the package.
61+ // When the returned strategy is run, it may either return the cached
5562// package immediately, wait for an in-progress load to complete,
5663// or perform the load itself.
5764//
58- // getLoadStratagy will not block, but the returned function may block.
59- func (pc * packageCache ) getLoadStratagy (importPath string ) loadStrategy {
65+ // getLoadStrategy will not block, but the returned function may block.
66+ func (pc * packageCache ) getLoadStrategy (importPath string ) loadStrategy {
6067 pc .lock .Lock ()
6168 defer pc .lock .Unlock ()
6269
@@ -75,7 +82,7 @@ func (pc *packageCache) getLoadStratagy(importPath string) loadStrategy {
7582 return pc .startLoading (importPath , ch )
7683}
7784
78- // alreadyLoaded returns a load stratagy that returns the cached sources.
85+ // alreadyLoaded returns a load strategy that returns the cached sources.
7986// The given cached sources must be the sources that are already loaded in the cache.
8087func (pc * packageCache ) alreadyLoaded (cached * sources.Sources ) loadStrategy {
8188 return func (srcs * sources.Sources ) (loadResult , error ) {
@@ -84,7 +91,7 @@ func (pc *packageCache) alreadyLoaded(cached *sources.Sources) loadStrategy {
8491 }
8592}
8693
87- // alreadyInprogress returns a load stratagy that waits for an in-progress load to complete.
94+ // alreadyInprogress returns a load strategy that waits for an in-progress load to complete.
8895// The given channel will be waited on until it is closed, indicating the load is complete
8996// and the sources should now be in the cache.
9097func (pc * packageCache ) alreadyInprogress (importPath string , ch chan struct {}) loadStrategy {
@@ -105,26 +112,25 @@ func (pc *packageCache) alreadyInprogress(importPath string, ch chan struct{}) l
105112 }
106113}
107114
108- // startLoading returns a load stratagy that performs the package load via a network request.
115+ // startLoading returns a load strategy that performs the package load via a network request.
109116// This occurs when the package is not cached and not currently in progress.
110117// The given channel will be closed when the load is complete to indicate to any
111118// other processed waiting on the load that it is done.
112119func (pc * packageCache ) startLoading (importPath string , ch chan struct {}) loadStrategy {
113120 return func (srcs * sources.Sources ) (loadResult , error ) {
114121 fetched , err := pc .fetcher .FetchPackage (importPath )
115- if err != nil {
116- delete (pc .inprogress , importPath )
117- close (ch )
118- return loadFailed , err
119- }
120122
121123 pc .lock .Lock ()
122124 defer pc .lock .Unlock ()
125+ defer close (ch )
126+ defer delete (pc .inprogress , importPath )
127+
128+ if err != nil {
129+ return loadFailed , err
130+ }
123131
124132 pc .cached [importPath ] = fetched
125133 * srcs = * fetched // Shallow copy the fetched sources into passed in sources.
126- delete (pc .inprogress , importPath )
127- close (ch )
128134 return loadFetched , nil
129135 }
130136}
0 commit comments