PublicDashboards: Make mixed datasource calls concurrently (#56421)

PublicDashboards: Make mixed datasource calls concurrently
This commit is contained in:
juanicabanas 2022-10-05 18:45:17 -03:00 committed by GitHub
parent d9cc292066
commit 69c49f6ba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 9 deletions

View File

@ -26,6 +26,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"golang.org/x/sync/errgroup"
) )
func ProvideService( func ProvideService(
@ -90,18 +91,31 @@ func (s *Service) QueryDataMultipleSources(ctx context.Context, user *user.Signe
} else { } else {
resp := backend.NewQueryDataResponse() resp := backend.NewQueryDataResponse()
// create new reqDTO with only the queries for that datasource g, ctx := errgroup.WithContext(ctx)
results := make([]backend.Responses, len(byDataSource))
for _, queries := range byDataSource { for _, queries := range byDataSource {
subDTO := reqDTO.CloneWithQueries(queries) dataSourceQueries := queries
g.Go(func() error {
subDTO := reqDTO.CloneWithQueries(dataSourceQueries)
subResp, err := s.QueryData(ctx, user, skipCache, subDTO, handleExpressions) subResp, err := s.QueryData(ctx, user, skipCache, subDTO, handleExpressions)
if err != nil { if err == nil {
return nil, err results = append(results, subResp.Responses)
} }
for refId, queryResponse := range subResp.Responses { return err
resp.Responses[refId] = queryResponse })
}
if err := g.Wait(); err != nil {
return nil, err
}
for _, result := range results {
for refId, dataResponse := range result {
resp.Responses[refId] = dataResponse
} }
} }

View File

@ -112,6 +112,43 @@ func TestQueryDataMultipleSources(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
}) })
t.Run("error is returned when one of the queries fails", func(t *testing.T) {
tc := setup(t)
query1, _ := simplejson.NewJson([]byte(`
{
"datasource": {
"type": "mysql",
"uid": "ds1"
}
}
`))
query2, _ := simplejson.NewJson([]byte(`
{
"datasource": {
"type": "prometheus",
"uid": "ds2"
},
"queryType": "FAIL"
}
`))
queries := []*simplejson.Json{query1, query2}
reqDTO := dtos.MetricRequest{
From: "2022-01-01",
To: "2022-01-02",
Queries: queries,
Debug: false,
PublicDashboardAccessToken: "abc123",
HTTPRequest: nil,
}
_, err := tc.queryService.QueryDataMultipleSources(context.Background(), nil, true, reqDTO, false)
require.Error(t, err)
})
} }
func TestQueryData(t *testing.T) { func TestQueryData(t *testing.T) {
@ -255,7 +292,6 @@ func (c *fakeDataSourceCache) GetDatasourceByUID(ctx context.Context, datasource
type fakePluginClient struct { type fakePluginClient struct {
plugins.Client plugins.Client
req *backend.QueryDataRequest req *backend.QueryDataRequest
} }
@ -267,5 +303,9 @@ func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryData
return nil, errors.New("cant query an expression datasource") return nil, errors.New("cant query an expression datasource")
} }
if req.Queries[0].QueryType == "FAIL" {
return nil, errors.New("plugin client failed")
}
return &backend.QueryDataResponse{Responses: make(backend.Responses)}, nil return &backend.QueryDataResponse{Responses: make(backend.Responses)}, nil
} }