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/httpclient"
"golang.org/x/sync/errgroup"
)
func ProvideService(
@ -90,18 +91,31 @@ func (s *Service) QueryDataMultipleSources(ctx context.Context, user *user.Signe
} else {
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 {
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 {
return nil, err
}
if err == nil {
results = append(results, subResp.Responses)
}
for refId, queryResponse := range subResp.Responses {
resp.Responses[refId] = queryResponse
return err
})
}
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)
})
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) {
@ -255,7 +292,6 @@ func (c *fakeDataSourceCache) GetDatasourceByUID(ctx context.Context, datasource
type fakePluginClient struct {
plugins.Client
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")
}
if req.Queries[0].QueryType == "FAIL" {
return nil, errors.New("plugin client failed")
}
return &backend.QueryDataResponse{Responses: make(backend.Responses)}, nil
}