Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pluginize Persisted Operations #1277

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions router-tests/persisted_operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func TestPersistedOperationsCache(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"employees":[{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Snappy","__typename":"Alligator"}]}},{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}},{"details":{"pets":[{"name":"Blotch","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Grayone","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Rusty","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Manya","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Peach","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Panda","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"},{"name":"Mommy","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Terry","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Tilda","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Vasya","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"}]}},{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Vanson","__typename":"Mouse"}]}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Pepper","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"}]}}]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "HIT", res.Response.Header.Get(core.ExecutionPlanCacheHeader))
}

Expand Down Expand Up @@ -170,7 +170,7 @@ func TestPersistedOperationsCache(t *testing.T) {
}, func(t *testing.T, xEnv *testenv.Environment) {
sendTwoRequests(t, xEnv)
numberOfCDNRequests := retrieveNumberOfCDNRequests(t, xEnv.CDN.URL)
require.Equal(t, 2, numberOfCDNRequests)
require.Equal(t, 3, numberOfCDNRequests)
})
})
}
Expand Down Expand Up @@ -198,7 +198,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"withAligators": true,"withCats": true,"skipDogs": false,"skipMouses": true}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employees":[{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Snappy","__typename":"Alligator","class":"REPTILE","dangerous":"yes","gender":"UNKNOWN"}]}},{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}},{"details":{"pets":[{"name":"Blotch","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Grayone","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Rusty","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Manya","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Peach","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Panda","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"},{"name":"Mommy","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Terry","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Tilda","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Vasya","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"}]}},{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Vanson","__typename":"Mouse"}]}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Pepper","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"}]}}]}}`, res.Body)

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -218,7 +218,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"withAligators": false,"withCats": true,"skipDogs": false,"skipMouses": true}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employees":[{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Snappy","__typename":"Alligator"}]}},{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}},{"details":{"pets":[{"name":"Blotch","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Grayone","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Rusty","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Manya","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Peach","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"STREET"},{"name":"Panda","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"},{"name":"Mommy","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"STREET"},{"name":"Terry","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Tilda","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"},{"name":"Vasya","__typename":"Cat","class":"MAMMAL","gender":"MALE","type":"HOME"}]}},{"details":{"pets":null}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Vanson","__typename":"Mouse"}]}},{"details":{"pets":null}},{"details":{"pets":[{"name":"Pepper","__typename":"Cat","class":"MAMMAL","gender":"FEMALE","type":"HOME"}]}}]}}`, res.Body)

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -238,7 +238,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"id":4,"withAligators": false,"withCats": true,"skipDogs": false,"skipMouses": true}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employee":{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}}}}`, res.Body)

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -248,7 +248,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"id":4,"withCats": true,"skipDogs": false,"skipMouses": true,"withAligators": false}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employee":{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}}}}`, res.Body)

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -268,7 +268,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"withCats": true,"skipDogs": false,"skipMouses": true,"withAligators": false}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employee":{"details":{"pets":[{"name":"Abby","__typename":"Dog","breed":"GOLDEN_RETRIEVER","class":"MAMMAL","gender":"FEMALE"},{"name":"Survivor","__typename":"Pony"}]}}}}`, res.Body)

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -278,7 +278,7 @@ func TestPersistedOperationCacheWithVariables(t *testing.T) {
Variables: []byte(`{"withCats": true,"skipDogs": false,"skipMouses": true,"withAligators": false,"id":3}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employee":{"details":{"pets":[{"name":"Snappy","__typename":"Alligator"}]}}}}`, res.Body)
})
}
Expand All @@ -305,7 +305,7 @@ func TestPersistedOperationsWithNestedVariablesExtraction(t *testing.T) {
Variables: []byte(`{"arg":"a"}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"rootFieldWithListOfInputArg":[{"arg":"a"}]}}`, res.Body)
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"NormalizationQuery"`),
Expand All @@ -314,7 +314,7 @@ func TestPersistedOperationsWithNestedVariablesExtraction(t *testing.T) {
Variables: []byte(`{"arg":"b"}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"rootFieldWithListOfInputArg":[{"arg":"b"}]}}`, res.Body)
})
}
Expand All @@ -339,7 +339,7 @@ func TestPersistedOperationCacheWithVariablesAndDefaultValues(t *testing.T) {
Variables: []byte(`{}`),
})
require.NoError(t, err)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, `{"data":{"employee":{"details":{"forename":"Jens","surname":"Neuse"}}}}`, res.Body)
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Expand All @@ -358,7 +358,7 @@ func TestPersistedOperationCacheWithVariablesAndDefaultValues(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"employee":{"details":{"forename":"Jens"}}}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "skipVariableWithDefault"}}`),
Expand All @@ -376,7 +376,7 @@ func TestPersistedOperationCacheWithVariablesAndDefaultValues(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"employee":{"details":{"forename":"Jens","surname":"Neuse"}}}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
})
}

Expand All @@ -401,7 +401,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["a"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "listArgQuery"}}`),
Expand All @@ -410,7 +410,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["b"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))

res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Expand All @@ -429,7 +429,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["a"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "listArgQueryWithDefault"}}`),
Expand All @@ -438,7 +438,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["b"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
OperationName: []byte(`"MyQuery"`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "listArgQueryWithDefault"}}`),
Expand All @@ -447,7 +447,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["c"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))

// nested list of enums
res, err = xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Expand All @@ -467,7 +467,7 @@ func TestPersistedOperationCacheWithVariablesCoercion(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithInput":"B"}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))
})
}

Expand Down
4 changes: 2 additions & 2 deletions router-tests/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -711,11 +711,11 @@ func TestTelemetry(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, `{"data":{"rootFieldWithListArg":["a"]}}`, res.Body)
require.Equal(t, "HIT", res.Response.Header.Get(core.PersistedOperationCacheHeader))
require.Equal(t, "MISS", res.Response.Header.Get(core.PersistedOperationCacheHeader))

sn = exporter.GetSpans().Snapshots()

require.Len(t, sn, 8, "expected 8 spans, got %d", len(sn))
require.Len(t, sn, 9, "expected 9 spans, got %d", len(sn))
require.NotEqualf(t, "Load Persisted Operation", sn[1].Name(), "excepted no span because it was a cache hit")
})
})
Expand Down
37 changes: 8 additions & 29 deletions router/core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package core

import (
"context"
"github.com/wundergraph/cosmo/router/pkg/config"
"net/http"
"net/url"
"strconv"
Expand All @@ -11,11 +10,11 @@ import (

graphqlmetrics "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/graphqlmetrics/v1"
"github.com/wundergraph/cosmo/router/pkg/otel"
"github.com/wundergraph/cosmo/router/pkg/clientinfo"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/httpclient"
"go.opentelemetry.io/otel/attribute"

"github.com/wundergraph/cosmo/router/pkg/authentication"
ctrace "github.com/wundergraph/cosmo/router/pkg/trace"

"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
"go.uber.org/zap"
Expand All @@ -34,26 +33,6 @@ type Subgraph struct {
UrlString string
}

type ClientInfo struct {
// Name contains the client name, derived from the request headers
Name string
// Version contains the client version, derived from the request headers
Version string
// WGRequestToken contains the token to authenticate the request from the platform
WGRequestToken string
}

func NewClientInfoFromRequest(r *http.Request, clientHeader config.ClientHeader) *ClientInfo {
clientName := ctrace.GetClientHeader(r.Header, []string{clientHeader.Name, "graphql-client-name", "apollographql-client-name"}, "unknown")
clientVersion := ctrace.GetClientHeader(r.Header, []string{clientHeader.Version, "graphql-client-version", "apollographql-client-version"}, "missing")
requestToken := r.Header.Get("X-WG-Token")
return &ClientInfo{
Name: clientName,
Version: clientVersion,
WGRequestToken: requestToken,
}
}

type RequestContext interface {
// ResponseWriter is the original response writer received by the router.
ResponseWriter() http.ResponseWriter
Expand Down Expand Up @@ -333,8 +312,8 @@ type OperationContext interface {
Hash() uint64
// Content is the content of the operation
Content() string
// ClientInfo returns information about the client that initiated this operation
ClientInfo() ClientInfo
// DetailedClientInfo returns information about the client that initiated this operation
DetailedClientInfo() clientinfo.DetailedClientInfo
}

var _ OperationContext = (*operationContext)(nil)
Expand All @@ -359,7 +338,7 @@ type operationContext struct {
content string
variables []byte
files []httpclient.File
clientInfo *ClientInfo
detailedClientInfo clientinfo.DetailedClientInfo
// preparedPlan is the prepared plan of the operation
preparedPlan *planWithMetaData
traceOptions resolve.TraceOptions
Expand Down Expand Up @@ -393,8 +372,8 @@ func (o *operationContext) setAttributes() {
numberOfAttributes += 1
}
o.attributes = make([]attribute.KeyValue, numberOfAttributes)
o.attributes[0] = otel.WgClientName.String(o.clientInfo.Name)
o.attributes[1] = otel.WgClientVersion.String(o.clientInfo.Version)
o.attributes[0] = otel.WgClientName.String(o.detailedClientInfo.Name())
o.attributes[1] = otel.WgClientVersion.String(o.detailedClientInfo.Version())
o.attributes[2] = otel.WgOperationName.String(o.Name())
o.attributes[3] = otel.WgOperationType.String(o.Type())
o.attributes[4] = otel.WgOperationProtocol.String(o.Protocol().String())
Expand Down Expand Up @@ -440,8 +419,8 @@ func (o *operationContext) Protocol() OperationProtocol {
return o.protocol
}

func (o *operationContext) ClientInfo() ClientInfo {
return *o.clientInfo
func (o *operationContext) DetailedClientInfo() clientinfo.DetailedClientInfo {
return o.detailedClientInfo
}

// isMutationRequest returns true if the current request is a mutation request
Expand Down
Loading
Loading