Skip to content

Commit 34d02e9

Browse files
committed
feature: significantly increase build speed
Signed-off-by: Valery Piashchynski <[email protected]>
1 parent f850ca2 commit 34d02e9

File tree

4 files changed

+209
-68
lines changed

4 files changed

+209
-68
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@
1717
# Added by cargo
1818
**/target
1919
**/plugins_dev.toml
20-
.vscode
20+
.vscode
21+
rr

github/pool.go

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package github
2+
3+
import (
4+
"bufio"
5+
"context"
6+
"fmt"
7+
"net/http"
8+
"path"
9+
"strings"
10+
"sync"
11+
"time"
12+
13+
"github.com/google/go-github/v49/github"
14+
"github.com/roadrunner-server/velox"
15+
"go.uber.org/zap"
16+
)
17+
18+
type processor struct {
19+
maxWorkers int
20+
errs []error
21+
wg sync.WaitGroup
22+
mu sync.Mutex
23+
log *zap.Logger
24+
queueCh chan *pcfg
25+
modinfo []*velox.ModulesInfo
26+
client *github.Client
27+
}
28+
29+
type pcfg struct {
30+
pluginCfg *velox.PluginConfig
31+
name string
32+
}
33+
34+
func newPool(log *zap.Logger, client *github.Client) *processor {
35+
p := &processor{
36+
maxWorkers: 10,
37+
log: log,
38+
client: client,
39+
modinfo: make([]*velox.ModulesInfo, 0, 10),
40+
queueCh: make(chan *pcfg, 1),
41+
wg: sync.WaitGroup{},
42+
mu: sync.Mutex{},
43+
errs: make([]error, 0, 1),
44+
}
45+
46+
// start the processor
47+
p.run()
48+
49+
return p
50+
}
51+
52+
func (p *processor) run() {
53+
for i := 0; i < p.maxWorkers; i++ {
54+
go func() {
55+
for v := range p.queueCh {
56+
modInfo := new(velox.ModulesInfo)
57+
p.log.Debug("[FETCHING PLUGIN DATA]",
58+
zap.String("repository", v.pluginCfg.Repo),
59+
zap.String("owner", v.pluginCfg.Owner),
60+
zap.String("folder", v.pluginCfg.Folder),
61+
zap.String("plugin", v.name),
62+
zap.String("ref", v.pluginCfg.Ref),
63+
)
64+
65+
if v.pluginCfg.Ref == "" {
66+
p.mu.Lock()
67+
p.errs = append(p.errs, fmt.Errorf("ref can't be empty"))
68+
p.mu.Unlock()
69+
p.wg.Done()
70+
continue
71+
}
72+
73+
rc, resp, err := p.client.Repositories.DownloadContents(context.Background(),
74+
v.pluginCfg.Owner,
75+
v.pluginCfg.Repo,
76+
path.Join(v.pluginCfg.Folder, "go.mod"), &github.RepositoryContentGetOptions{Ref: v.pluginCfg.Ref},
77+
)
78+
if err != nil {
79+
p.mu.Lock()
80+
p.errs = append(p.errs, err)
81+
p.mu.Unlock()
82+
p.wg.Done()
83+
continue
84+
}
85+
86+
if resp.StatusCode != http.StatusOK {
87+
p.mu.Lock()
88+
p.errs = append(p.errs, fmt.Errorf("bad response status: %d", resp.StatusCode))
89+
p.mu.Unlock()
90+
p.wg.Done()
91+
continue
92+
}
93+
94+
rdr := bufio.NewReader(rc)
95+
ret, err := rdr.ReadString('\n')
96+
if err != nil {
97+
p.mu.Lock()
98+
p.errs = append(p.errs, err)
99+
p.mu.Unlock()
100+
p.wg.Done()
101+
continue
102+
}
103+
104+
p.log.Debug("[READING MODULE INFO]", zap.String("plugin", v.name), zap.String("mod", ret))
105+
106+
// module github.com/roadrunner-server/logger/v2, we split and get the second part
107+
retMod := strings.Split(ret, " ")
108+
if len(retMod) < 2 {
109+
p.mu.Lock()
110+
p.errs = append(p.errs, fmt.Errorf("failed to parse module info for the plugin: %s", ret))
111+
p.mu.Unlock()
112+
p.wg.Done()
113+
continue
114+
}
115+
116+
err = resp.Body.Close()
117+
if err != nil {
118+
p.mu.Lock()
119+
p.errs = append(p.errs, err)
120+
p.mu.Unlock()
121+
p.wg.Done()
122+
continue
123+
}
124+
125+
modInfo.ModuleName = strings.TrimRight(retMod[1], "\n")
126+
127+
p.log.Debug("[REQUESTING COMMIT SHA-1]", zap.String("plugin", v.name), zap.String("ref", v.pluginCfg.Ref))
128+
commits, rsp, err := p.client.Repositories.ListCommits(context.Background(), v.pluginCfg.Owner, v.pluginCfg.Repo, &github.CommitsListOptions{
129+
SHA: v.pluginCfg.Ref,
130+
Until: time.Now(),
131+
ListOptions: github.ListOptions{
132+
Page: 1,
133+
PerPage: 1,
134+
},
135+
})
136+
if err != nil {
137+
p.mu.Lock()
138+
p.errs = append(p.errs, err)
139+
p.mu.Unlock()
140+
p.wg.Done()
141+
continue
142+
}
143+
144+
if rsp.StatusCode != http.StatusOK {
145+
p.mu.Lock()
146+
p.errs = append(p.errs, fmt.Errorf("bad response status: %d", rsp.StatusCode))
147+
p.mu.Unlock()
148+
p.wg.Done()
149+
continue
150+
}
151+
152+
for j := 0; j < len(commits); j++ {
153+
modInfo.Version = *commits[j].SHA
154+
}
155+
156+
if v.pluginCfg.Replace != "" {
157+
p.log.Debug("[REPLACE REQUESTED]", zap.String("plugin", v.name), zap.String("path", v.pluginCfg.Replace))
158+
}
159+
160+
p.mu.Lock()
161+
p.modinfo = append(p.modinfo, modInfo)
162+
p.mu.Unlock()
163+
164+
p.wg.Done()
165+
}
166+
}()
167+
}
168+
}
169+
170+
func (p *processor) add(pjob *pcfg) {
171+
p.wg.Add(1)
172+
p.queueCh <- pjob
173+
}
174+
175+
func (p *processor) errors() []error {
176+
p.mu.Lock()
177+
defer p.mu.Unlock()
178+
return p.errs
179+
}
180+
181+
func (p *processor) moduleinfo() []*velox.ModulesInfo {
182+
p.mu.Lock()
183+
defer p.mu.Unlock()
184+
return p.modinfo
185+
}
186+
187+
func (p *processor) wait() {
188+
p.wg.Wait()
189+
}
190+
191+
func (p *processor) stop() {
192+
close(p.queueCh)
193+
}

github/repo.go

+13-66
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package github
22

33
import (
44
"archive/zip"
5-
"bufio"
65
"bytes"
76
"context"
87
"errors"
@@ -13,7 +12,6 @@ import (
1312
"path"
1413
"path/filepath"
1514
"strings"
16-
"time"
1715

1816
"github.com/google/go-github/v49/github"
1917
"github.com/roadrunner-server/velox"
@@ -30,6 +28,7 @@ const (
3028
GHRepo represents template repository
3129
*/
3230
type GHRepo struct {
31+
pool *processor
3332
client *github.Client
3433
config *velox.Config
3534
log *zap.Logger
@@ -46,6 +45,7 @@ func NewGHRepoInfo(cfg *velox.Config, log *zap.Logger) *GHRepo {
4645
}
4746

4847
return &GHRepo{
48+
pool: newPool(log, github.NewClient(client)),
4949
log: log,
5050
config: cfg,
5151
client: github.NewClient(client),
@@ -198,74 +198,21 @@ func extract(dest string, zf *zip.File) error {
198198
// https://github.com/spiral/roadrunner-binary/archive/refs/tags/v2.7.0.zip
199199

200200
func (r *GHRepo) GetPluginsModData() ([]*velox.ModulesInfo, error) {
201-
modInfoRet := make([]*velox.ModulesInfo, 0, 5)
202-
203201
for k, v := range r.config.GitHub.Plugins {
204-
modInfo := new(velox.ModulesInfo)
205-
r.log.Debug("[FETCHING PLUGIN DATA]", zap.String("repository", v.Repo), zap.String("owner", v.Owner), zap.String("folder", v.Folder), zap.String("plugin", k), zap.String("ref", v.Ref))
206-
207-
if v.Ref == "" {
208-
return nil, errors.New("ref can't be empty")
209-
}
210-
211-
rc, resp, err := r.client.Repositories.DownloadContents(context.Background(), v.Owner, v.Repo, path.Join(v.Folder, "go.mod"), &github.RepositoryContentGetOptions{Ref: v.Ref})
212-
if err != nil {
213-
return nil, err
214-
}
215-
216-
if resp.StatusCode != http.StatusOK {
217-
return nil, fmt.Errorf("bad response status: %d", resp.StatusCode)
218-
}
219-
220-
rdr := bufio.NewReader(rc)
221-
ret, err := rdr.ReadString('\n')
222-
if err != nil {
223-
return nil, err
224-
}
225-
226-
r.log.Debug("[READING MODULE INFO]", zap.String("plugin", k), zap.String("mod", ret))
227-
228-
// module github.com/roadrunner-server/logger/v2, we split and get the second part
229-
retMod := strings.Split(ret, " ")
230-
if len(retMod) < 2 {
231-
return nil, fmt.Errorf("failed to parse module info for the plugin: %s", ret)
232-
}
233-
234-
err = resp.Body.Close()
235-
if err != nil {
236-
return nil, err
237-
}
238-
239-
modInfo.ModuleName = strings.TrimRight(retMod[1], "\n")
240-
241-
r.log.Debug("[REQUESTING COMMIT SHA-1]", zap.String("plugin", k), zap.String("ref", v.Ref))
242-
commits, rsp, err := r.client.Repositories.ListCommits(context.Background(), v.Owner, v.Repo, &github.CommitsListOptions{
243-
SHA: v.Ref,
244-
Until: time.Now(),
245-
ListOptions: github.ListOptions{
246-
Page: 1,
247-
PerPage: 1,
248-
},
202+
r.pool.add(&pcfg{
203+
pluginCfg: v,
204+
name: k,
249205
})
250-
if err != nil {
251-
return nil, err
252-
}
253-
254-
if rsp.StatusCode != http.StatusOK {
255-
return nil, fmt.Errorf("bad response status: %d", rsp.StatusCode)
256-
}
257-
258-
for i := 0; i < len(commits); i++ {
259-
modInfo.Version = *commits[i].SHA
260-
}
206+
}
261207

262-
if v.Replace != "" {
263-
r.log.Debug("[REPLACE REQUESTED]", zap.String("plugin", k), zap.String("path", v.Replace))
264-
}
208+
r.pool.wait()
265209

266-
modInfo.Replace = v.Replace
267-
modInfoRet = append(modInfoRet, modInfo)
210+
if len(r.pool.errors()) != 0 {
211+
return nil, errors.Join(r.pool.errors()...)
268212
}
269213

270-
return modInfoRet, nil
214+
mi := r.pool.moduleinfo()
215+
r.pool.stop()
216+
217+
return mi, nil
271218
}

velox_rr_v2023.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,5 @@ ref = "v2023.3.0"
8686
# test_plugin_2 = { ref = "main", owner = "rustatian", repository = "36405235" }
8787
#
8888
[log]
89-
level = "debug"
89+
level = "error"
9090
mode = "development"

0 commit comments

Comments
 (0)