@@ -16,8 +16,18 @@ import (
1616 "github.com/go-semantic-release/plugin-registry/internal/batch"
1717 "github.com/go-semantic-release/plugin-registry/internal/config"
1818 "github.com/go-semantic-release/plugin-registry/pkg/registry"
19+ "golang.org/x/sync/errgroup"
1920)
2021
22+ type pluginBatchError struct {
23+ PluginName string
24+ Err error
25+ }
26+
27+ func (e * pluginBatchError ) Error () string {
28+ return fmt .Sprintf ("plugin batch error (%s): %s" , e .PluginName , e .Err .Error ())
29+ }
30+
2131func validateAndCreatePluginResponses (batchRequest * registry.BatchRequest ) (registry.BatchResponsePlugins , error ) {
2232 err := batchRequest .Validate ()
2333 if err != nil {
@@ -82,23 +92,42 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
8292 return
8393 }
8494
95+ // TODO: this could be done in parallel
96+ errGroup , groupCtx := errgroup .WithContext (r .Context ())
97+ errGroup .SetLimit (5 )
8598 for _ , pluginResponse := range batchResponse .Plugins {
86- p := config .Plugins .Find (pluginResponse .FullName )
87- foundRelease , rErr := p .GetReleaseWithVersionConstraint (r .Context (), s .db , pluginResponse .VersionConstraint )
88- if rErr != nil {
89- s .writeJSONError (w , r , http .StatusBadRequest , rErr , fmt .Sprintf ("could not resolve plugin %s" , pluginResponse .FullName ))
90- return
91- }
92- foundAsset := foundRelease .Assets [batchResponse .GetOSArch ()]
93- if foundAsset == nil {
94- s .writeJSONError (w , r , http .StatusBadRequest , fmt .Errorf ("could not find %s asset for plugin %s" , batchResponse .GetOSArch (), pluginResponse .FullName ))
95- return
96- }
97-
98- pluginResponse .Version = foundRelease .Version
99- pluginResponse .FileName = foundAsset .FileName
100- pluginResponse .URL = foundAsset .URL
101- pluginResponse .Checksum = foundAsset .Checksum
99+ pluginResponse := pluginResponse
100+ errGroup .Go (func () error {
101+ p := config .Plugins .Find (pluginResponse .FullName )
102+ foundRelease , rErr := p .GetReleaseWithVersionConstraint (groupCtx , s .db , pluginResponse .VersionConstraint )
103+ if rErr != nil {
104+ return & pluginBatchError {
105+ PluginName : pluginResponse .FullName ,
106+ Err : rErr ,
107+ }
108+ }
109+ foundAsset := foundRelease .Assets [batchResponse .GetOSArch ()]
110+ if foundAsset == nil {
111+ return & pluginBatchError {
112+ PluginName : pluginResponse .FullName ,
113+ Err : fmt .Errorf ("could not find %s asset" , batchResponse .GetOSArch ()),
114+ }
115+ }
116+ pluginResponse .Version = foundRelease .Version
117+ pluginResponse .FileName = foundAsset .FileName
118+ pluginResponse .URL = foundAsset .URL
119+ pluginResponse .Checksum = foundAsset .Checksum
120+ return nil
121+ })
122+ }
123+ err = errGroup .Wait ()
124+ pbErr := & pluginBatchError {}
125+ if errors .As (err , & pbErr ) {
126+ s .writeJSONError (w , r , http .StatusBadRequest , pbErr , fmt .Sprintf ("could not resolve plugin %s" , pbErr .PluginName ))
127+ return
128+ } else if err != nil {
129+ s .writeJSONError (w , r , http .StatusBadRequest , err , "could not resolve plugins" )
130+ return
102131 }
103132
104133 // calculate the hash of the response, this now includes the plugin versions
@@ -108,6 +137,7 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
108137 batchResponse .DownloadURL = s .config .GetPublicPluginCacheDownloadURL (archiveKey )
109138
110139 // allow only one batch archive process at a time
140+ // TODO: this might be to conservative, we could allow multiple archives to be created at the same time
111141 s .batchMu .Lock ()
112142 defer s .batchMu .Unlock ()
113143
0 commit comments