Skip to content

Commit 8bfa312

Browse files
authored
fix(coderd): parallelize queries to improve template insights performance (#9275)
1 parent d180df1 commit 8bfa312

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

coderd/insights.go

+37-25
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/google/uuid"
1010
"golang.org/x/exp/slices"
11+
"golang.org/x/sync/errgroup"
1112
"golang.org/x/xerrors"
1213

1314
"github.com/coder/coder/v2/coderd/database"
@@ -190,14 +191,18 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
190191
var usage database.GetTemplateInsightsRow
191192
var appUsage []database.GetTemplateAppInsightsRow
192193
var dailyUsage []database.GetTemplateDailyInsightsRow
194+
var parameterRows []database.GetTemplateParameterInsightsRow
193195

194-
// Use a transaction to ensure that we get consistent data between
195-
// the full and interval report.
196-
err := api.Database.InTx(func(tx database.Store) error {
197-
var err error
196+
eg, egCtx := errgroup.WithContext(ctx)
197+
eg.SetLimit(4)
198198

199+
// The following insights data queries have a theoretical chance to be
200+
// inconsistent between eachother when looking at "today", however, the
201+
// overhead from a transaction is not worth it.
202+
eg.Go(func() error {
203+
var err error
199204
if interval != "" {
200-
dailyUsage, err = tx.GetTemplateDailyInsights(ctx, database.GetTemplateDailyInsightsParams{
205+
dailyUsage, err = api.Database.GetTemplateDailyInsights(egCtx, database.GetTemplateDailyInsightsParams{
201206
StartTime: startTime,
202207
EndTime: endTime,
203208
TemplateIDs: templateIDs,
@@ -206,27 +211,49 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
206211
return xerrors.Errorf("get template daily insights: %w", err)
207212
}
208213
}
209-
210-
usage, err = tx.GetTemplateInsights(ctx, database.GetTemplateInsightsParams{
214+
return nil
215+
})
216+
eg.Go(func() error {
217+
var err error
218+
usage, err = api.Database.GetTemplateInsights(egCtx, database.GetTemplateInsightsParams{
211219
StartTime: startTime,
212220
EndTime: endTime,
213221
TemplateIDs: templateIDs,
214222
})
215223
if err != nil {
216224
return xerrors.Errorf("get template insights: %w", err)
217225
}
218-
219-
appUsage, err = tx.GetTemplateAppInsights(ctx, database.GetTemplateAppInsightsParams{
226+
return nil
227+
})
228+
eg.Go(func() error {
229+
var err error
230+
appUsage, err = api.Database.GetTemplateAppInsights(egCtx, database.GetTemplateAppInsightsParams{
220231
StartTime: startTime,
221232
EndTime: endTime,
222233
TemplateIDs: templateIDs,
223234
})
224235
if err != nil {
225236
return xerrors.Errorf("get template app insights: %w", err)
226237
}
238+
return nil
239+
})
227240

241+
// Template parameter insights have no risk of inconsistency with the other
242+
// insights.
243+
eg.Go(func() error {
244+
var err error
245+
parameterRows, err = api.Database.GetTemplateParameterInsights(ctx, database.GetTemplateParameterInsightsParams{
246+
StartTime: startTime,
247+
EndTime: endTime,
248+
TemplateIDs: templateIDs,
249+
})
250+
if err != nil {
251+
return xerrors.Errorf("get template parameter insights: %w", err)
252+
}
228253
return nil
229-
}, nil)
254+
})
255+
256+
err := eg.Wait()
230257
if httpapi.Is404Error(err) {
231258
httpapi.ResourceNotFound(rw)
232259
return
@@ -239,21 +266,6 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
239266
return
240267
}
241268

242-
// Template parameter insights have no risk of inconsistency with the other
243-
// insights, so we don't need to perform this in a transaction.
244-
parameterRows, err := api.Database.GetTemplateParameterInsights(ctx, database.GetTemplateParameterInsightsParams{
245-
StartTime: startTime,
246-
EndTime: endTime,
247-
TemplateIDs: templateIDs,
248-
})
249-
if err != nil {
250-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
251-
Message: "Internal error fetching template parameter insights.",
252-
Detail: err.Error(),
253-
})
254-
return
255-
}
256-
257269
parametersUsage, err := db2sdk.TemplateInsightsParameters(parameterRows)
258270
if err != nil {
259271
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{

0 commit comments

Comments
 (0)