Skip to content

Commit

Permalink
TT-10962 (#6072)
Browse files Browse the repository at this point in the history
<!-- Provide a general summary of your changes in the Title above -->

[TT-10962](https://tyktech.atlassian.net/browse/TT-10962)

<!-- Describe your changes in detail -->

<!-- This project only accepts pull requests related to open issues. -->
<!-- If suggesting a new feature or change, please discuss it in an
issue first. -->
<!-- If fixing a bug, there should be an issue describing it with steps
to reproduce. -->
<!-- OSS: Please link to the issue here. Tyk: please create/link the
JIRA ticket. -->

<!-- Why is this change required? What problem does it solve? -->

<!-- Please describe in detail how you tested your changes -->
<!-- Include details of your testing environment, and the tests -->
<!-- you ran to see how your change affects other areas of the code,
etc. -->
<!-- This information is helpful for reviewers and QA. -->

<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Refactoring or add test (improvements in base code or adds test
coverage to functionality)

<!-- Go over all the following points, and put an `x` in all the boxes
that apply -->
<!-- If there are no documentation updates required, mark the item as
checked. -->
<!-- Raise up any additional concerns not covered by the checklist. -->

- [ ] I ensured that the documentation is up to date
- [ ] I explained why this PR updates go.mod in detail with reasoning
why it's required
- [ ] I would like a code coverage CI quality gate exception and have
explained why

[TT-10962]:
https://tyktech.atlassian.net/browse/TT-10962?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

___

bug_fix

___

- Disabled the `EnableSingleFlight` feature in both `ProxyOnly` and
`UniversalDataGraph` adapters to address existing issues.

___

<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>adapter_proxy_only.go</strong><dd><code>Disable
SingleFlight in ProxyOnly Adapter</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>

apidef/adapter/gqlengineadapter/adapter_proxy_only.go
<li>Disabled <code>EnableSingleFlight</code> feature by setting its
value to <code>false</code>.<br>

</details>

  </td>
<td><a
href="https://pull/6072/files#diff-c3d2491b83997adf408861dc51e396c95e2baabba8286309f5c344cfcee7d78b">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>
</tr>

<tr>
  <td>
    <details>
<summary><strong>adapter_udg.go</strong><dd><code>Disable SingleFlight
in UniversalDataGraph Adapter</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>

apidef/adapter/gqlengineadapter/adapter_udg.go
<li>Disabled <code>EnableSingleFlight</code> feature by setting its
value to <code>false</code>.<br>

</details>

  </td>
<td><a
href="https://pull/6072/files#diff-f01b6f97ed0e7bbe78b66c8d0c5e34fbabf49683a4a0784f7b25ebaabe97c03b">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>
</tr>
</table></td></tr></tr></tbody></table>

___

> ✨ **PR-Agent usage**:
>Comment `/help` on the PR to get a list of all available PR-Agent tools
and their descriptions

Co-authored-by: Shakira Salazar <69164527+rhianeKobar@users.noreply.github.com>
(cherry picked from commit 9ed401d)
  • Loading branch information
kofoworola authored and Tyk Bot committed Mar 4, 2024
1 parent 98a0a40 commit e6f533a
Show file tree
Hide file tree
Showing 2 changed files with 283 additions and 0 deletions.
59 changes: 59 additions & 0 deletions apidef/adapter/gqlengineadapter/adapter_proxy_only.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package gqlengineadapter

import (
"net/http"
"strings"

graphqlDataSource "github.com/TykTechnologies/graphql-go-tools/pkg/engine/datasource/graphql_datasource"
"github.com/TykTechnologies/graphql-go-tools/pkg/graphql"

"github.com/TykTechnologies/tyk/apidef"
)

type ProxyOnly struct {
ApiDefinition *apidef.APIDefinition
HttpClient *http.Client
StreamingClient *http.Client
Schema *graphql.Schema

subscriptionClientFactory graphqlDataSource.GraphQLSubscriptionClientFactory
}

func (p *ProxyOnly) EngineConfig() (*graphql.EngineV2Configuration, error) {
var err error
if p.Schema == nil {
p.Schema, err = parseSchema(p.ApiDefinition.GraphQL.Schema)

Check failure on line 25 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: parseSchema

Check failure on line 25 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: parseSchema
if err != nil {
return nil, err
}
}

staticHeaders := make(http.Header)
for key, value := range p.ApiDefinition.GraphQL.Proxy.RequestHeaders {
staticHeaders.Set(key, value)
}

url := p.ApiDefinition.Proxy.TargetURL
if strings.HasPrefix(url, "tyk://") {
url = strings.ReplaceAll(url, "tyk://", "http://")
staticHeaders.Set(apidef.TykInternalApiHeader, "true")
}

upstreamConfig := graphql.ProxyUpstreamConfig{
URL: url,
StaticHeaders: staticHeaders,
SubscriptionType: graphqlSubscriptionType(p.ApiDefinition.GraphQL.Proxy.SubscriptionType),

Check failure on line 45 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: graphqlSubscriptionType

Check failure on line 45 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: graphqlSubscriptionType
}

v2Config, err := graphql.NewProxyEngineConfigFactory(
p.Schema,
upstreamConfig,
graphqlDataSource.NewBatchFactory(),
graphql.WithProxyHttpClient(p.HttpClient),
graphql.WithProxyStreamingClient(p.StreamingClient),
graphql.WithProxySubscriptionClientFactory(subscriptionClientFactoryOrDefault(p.subscriptionClientFactory)),

Check failure on line 54 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: subscriptionClientFactoryOrDefault

Check failure on line 54 in apidef/adapter/gqlengineadapter/adapter_proxy_only.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: subscriptionClientFactoryOrDefault
).EngineV2Configuration()

v2Config.EnableSingleFlight(false)
return &v2Config, err
}
224 changes: 224 additions & 0 deletions apidef/adapter/gqlengineadapter/adapter_udg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
package gqlengineadapter

import (
"encoding/json"
"net/http"

graphqlDataSource "github.com/TykTechnologies/graphql-go-tools/pkg/engine/datasource/graphql_datasource"
kafkaDataSource "github.com/TykTechnologies/graphql-go-tools/pkg/engine/datasource/kafka_datasource"
restDataSource "github.com/TykTechnologies/graphql-go-tools/pkg/engine/datasource/rest_datasource"
"github.com/TykTechnologies/graphql-go-tools/pkg/engine/plan"
"github.com/TykTechnologies/graphql-go-tools/pkg/graphql"

"github.com/TykTechnologies/tyk/apidef"
)

type UniversalDataGraph struct {
ApiDefinition *apidef.APIDefinition
HttpClient *http.Client
StreamingClient *http.Client
Schema *graphql.Schema

subscriptionClientFactory graphqlDataSource.GraphQLSubscriptionClientFactory
}

func (u *UniversalDataGraph) EngineConfig() (*graphql.EngineV2Configuration, error) {
var err error
if u.Schema == nil {
u.Schema, err = parseSchema(u.ApiDefinition.GraphQL.Schema)

Check failure on line 28 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: parseSchema

Check failure on line 28 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: parseSchema
if err != nil {
return nil, err
}
}

conf := graphql.NewEngineV2Configuration(u.Schema)
conf.EnableSingleFlight(false)

fieldConfigs := u.engineConfigV2FieldConfigs()
datsSources, err := u.engineConfigV2DataSources()
if err != nil {
return nil, err
}

conf.SetFieldConfigurations(fieldConfigs)
conf.SetDataSources(datsSources)

return &conf, nil
}

func (u *UniversalDataGraph) engineConfigV2FieldConfigs() (planFieldConfigs plan.FieldConfigurations) {
for _, fc := range u.ApiDefinition.GraphQL.Engine.FieldConfigs {
planFieldConfig := plan.FieldConfiguration{
TypeName: fc.TypeName,
FieldName: fc.FieldName,
DisableDefaultMapping: fc.DisableDefaultMapping,
Path: fc.Path,
}

planFieldConfigs = append(planFieldConfigs, planFieldConfig)
}

generatedArgs := u.Schema.GetAllFieldArguments(graphql.NewSkipReservedNamesFunc())
generatedArgsAsLookupMap := graphql.CreateTypeFieldArgumentsLookupMap(generatedArgs)
u.engineConfigV2Arguments(&planFieldConfigs, generatedArgsAsLookupMap)

return planFieldConfigs
}

func (u *UniversalDataGraph) engineConfigV2DataSources() (planDataSources []plan.DataSourceConfiguration, err error) {
for _, ds := range u.ApiDefinition.GraphQL.Engine.DataSources {
planDataSource := plan.DataSourceConfiguration{
RootNodes: []plan.TypeField{},
}

for _, typeField := range ds.RootFields {
planTypeField := plan.TypeField{
TypeName: typeField.Type,
FieldNames: typeField.Fields,
}

planDataSource.RootNodes = append(planDataSource.RootNodes, planTypeField)
}

switch ds.Kind {
case apidef.GraphQLEngineDataSourceKindREST:
var restConfig apidef.GraphQLEngineDataSourceConfigREST
err = json.Unmarshal(ds.Config, &restConfig)
if err != nil {
return nil, err
}

planDataSource.Factory = &restDataSource.Factory{
Client: u.HttpClient,
}

urlWithoutQueryParams, queryConfigs, err := extractURLQueryParamsForEngineV2(restConfig.URL, restConfig.Query)

Check failure on line 95 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: extractURLQueryParamsForEngineV2

Check failure on line 95 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: extractURLQueryParamsForEngineV2
if err != nil {
return nil, err
}

planDataSource.Custom = restDataSource.ConfigJSON(restDataSource.Configuration{
Fetch: restDataSource.FetchConfiguration{
URL: urlWithoutQueryParams,
Method: restConfig.Method,
Body: restConfig.Body,
Query: queryConfigs,
Header: convertApiDefinitionHeadersToHttpHeaders(restConfig.Headers),

Check failure on line 106 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: convertApiDefinitionHeadersToHttpHeaders

Check failure on line 106 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: convertApiDefinitionHeadersToHttpHeaders
},
})

case apidef.GraphQLEngineDataSourceKindGraphQL:
var graphqlConfig apidef.GraphQLEngineDataSourceConfigGraphQL
err = json.Unmarshal(ds.Config, &graphqlConfig)
if err != nil {
return nil, err
}

if graphqlConfig.HasOperation {

Check failure on line 117 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

graphqlConfig.HasOperation undefined (type apidef.GraphQLEngineDataSourceConfigGraphQL has no field or method HasOperation)

Check failure on line 117 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

graphqlConfig.HasOperation undefined (type apidef.GraphQLEngineDataSourceConfigGraphQL has no field or method HasOperation)
planDataSource.Factory = &restDataSource.Factory{
Client: u.HttpClient,
}
planDataSource.Custom, err = generateRestDataSourceFromGraphql(graphqlConfig)

Check failure on line 121 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: generateRestDataSourceFromGraphql

Check failure on line 121 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: generateRestDataSourceFromGraphql
if err != nil {
return nil, err
}
break
}

planDataSource.Factory, err = createGraphQLDataSourceFactory(createGraphQLDataSourceFactoryParams{

Check failure on line 128 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: createGraphQLDataSourceFactory

Check failure on line 128 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undefined: createGraphQLDataSourceFactoryParams

Check failure on line 128 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: createGraphQLDataSourceFactory

Check failure on line 128 in apidef/adapter/gqlengineadapter/adapter_udg.go

View workflow job for this annotation

GitHub Actions / Go 1.16 Redis 5

undeclared name: createGraphQLDataSourceFactoryParams
graphqlConfig: graphqlConfig,
subscriptionClientFactory: subscriptionClientFactoryOrDefault(u.subscriptionClientFactory),
httpClient: u.HttpClient,
streamingClient: u.StreamingClient,
})
if err != nil {
return nil, err
}

planDataSource.Custom = graphqlDataSource.ConfigJson(graphqlDataSourceConfiguration(
graphqlConfig.URL,
graphqlConfig.Method,
graphqlConfig.Headers,
graphqlConfig.SubscriptionType,
))

case apidef.GraphQLEngineDataSourceKindKafka:
var kafkaConfig apidef.GraphQLEngineDataSourceConfigKafka
err = json.Unmarshal(ds.Config, &kafkaConfig)
if err != nil {
return nil, err
}

planDataSource.Factory = &kafkaDataSource.Factory{}
planDataSource.Custom = kafkaDataSource.ConfigJSON(kafkaDataSource.Configuration{
Subscription: kafkaDataSource.SubscriptionConfiguration{
BrokerAddresses: kafkaConfig.BrokerAddresses,
Topics: kafkaConfig.Topics,
GroupID: kafkaConfig.GroupID,
ClientID: kafkaConfig.ClientID,
KafkaVersion: kafkaConfig.KafkaVersion,
StartConsumingLatest: kafkaConfig.StartConsumingLatest,
BalanceStrategy: kafkaConfig.BalanceStrategy,
IsolationLevel: kafkaConfig.IsolationLevel,
SASL: kafkaConfig.SASL,
},
})
}

planDataSources = append(planDataSources, planDataSource)
}

err = u.determineChildNodes(planDataSources)
return planDataSources, err
}

func (u *UniversalDataGraph) engineConfigV2Arguments(fieldConfs *plan.FieldConfigurations, generatedArgs map[graphql.TypeFieldLookupKey]graphql.TypeFieldArguments) {
for i := range *fieldConfs {
if len(generatedArgs) == 0 {
return
}

lookupKey := graphql.CreateTypeFieldLookupKey((*fieldConfs)[i].TypeName, (*fieldConfs)[i].FieldName)
currentArgs, ok := generatedArgs[lookupKey]
if !ok {
continue
}

(*fieldConfs)[i].Arguments = createArgumentConfigurationsForArgumentNames(currentArgs.ArgumentNames...)
delete(generatedArgs, lookupKey)
}

for _, genArgs := range generatedArgs {
*fieldConfs = append(*fieldConfs, plan.FieldConfiguration{
TypeName: genArgs.TypeName,
FieldName: genArgs.FieldName,
Arguments: createArgumentConfigurationsForArgumentNames(genArgs.ArgumentNames...),
})
}
}

func (u *UniversalDataGraph) determineChildNodes(planDataSources []plan.DataSourceConfiguration) error {
for i := range planDataSources {
if _, ok := planDataSources[i].Factory.(*restDataSource.Factory); ok {
continue
}
for j := range planDataSources[i].RootNodes {
typeName := planDataSources[i].RootNodes[j].TypeName
for k := range planDataSources[i].RootNodes[j].FieldNames {
fieldName := planDataSources[i].RootNodes[j].FieldNames[k]
typeFields := u.Schema.GetAllNestedFieldChildrenFromTypeField(typeName, fieldName, graphql.NewIsDataSourceConfigV2RootFieldSkipFunc(planDataSources))

children := make([]plan.TypeField, 0)
for _, tf := range typeFields {
childNode := plan.TypeField{
TypeName: tf.TypeName,
FieldNames: tf.FieldNames,
}
children = append(children, childNode)
}
planDataSources[i].ChildNodes = append(planDataSources[i].ChildNodes, children...)
}
}
}
return nil
}

0 comments on commit e6f533a

Please sign in to comment.