Skip to content

Commit

Permalink
Support v0.1.0-rc.14 of the NDC spec
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac committed Feb 8, 2024
1 parent b35cfba commit c6d5337
Show file tree
Hide file tree
Showing 11 changed files with 1,136 additions and 603 deletions.
8 changes: 4 additions & 4 deletions codegen/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ import (
var defaultScalarTypes = schema.SchemaResponseScalarTypes{

Check failure on line 12 in codegen/schema.go

View workflow job for this annotation

GitHub Actions / Run Go lint and unit tests

var `defaultScalarTypes` is unused (unused)
"String": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{},
},
"Int": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{},
},
"Float": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{},
},
"Boolean": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{},
},
}

Expand Down
74 changes: 69 additions & 5 deletions connector/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"os"
"os/signal"
"strings"
"time"

"github.com/hasura/ndc-sdk-go/schema"
Expand Down Expand Up @@ -232,10 +233,10 @@ func (s *Server[RawConfiguration, Configuration, State]) Query(w http.ResponseWr
s.telemetry.queryLatencyHistogram.Record(r.Context(), time.Since(startTime).Seconds(), metric.WithAttributes(collectionAttr))
}

func (s *Server[RawConfiguration, Configuration, State]) Explain(w http.ResponseWriter, r *http.Request) {
func (s *Server[RawConfiguration, Configuration, State]) QueryExplain(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
logger := GetLogger(r.Context())
ctx, span := s.telemetry.Tracer.Start(r.Context(), "Explain", trace.WithSpanKind(trace.SpanKindServer))
ctx, span := s.telemetry.Tracer.Start(r.Context(), "Query Explain", trace.WithSpanKind(trace.SpanKindServer))
defer span.End()

attributes := []attribute.KeyValue{}
Expand Down Expand Up @@ -266,7 +267,69 @@ func (s *Server[RawConfiguration, Configuration, State]) Explain(w http.Response
execCtx, execSpan := s.telemetry.Tracer.Start(ctx, "Execute Explain")
defer execSpan.End()

response, err := s.connector.Explain(execCtx, s.configuration, s.state, &body)
response, err := s.connector.QueryExplain(execCtx, s.configuration, s.state, &body)
if err != nil {
status := writeError(w, logger, err)
statusAttributes := []attribute.KeyValue{
attribute.String("status", "failed"),
attribute.String("reason", fmt.Sprintf("%d", status)),
}
span.SetAttributes(attributes...)
s.telemetry.explainCounter.Add(r.Context(), 1, metric.WithAttributes(append(attributes, statusAttributes...)...))
return
}
execSpan.End()

statusAttribute := attribute.String("status", "success")
span.SetAttributes(statusAttribute)
_, responseSpan := s.telemetry.Tracer.Start(ctx, "Response")
writeJson(w, logger, http.StatusOK, response)
responseSpan.End()
s.telemetry.explainCounter.Add(r.Context(), 1, metric.WithAttributes(append(attributes, statusAttribute)...))

// record latency for success requests only
s.telemetry.explainLatencyHistogram.Record(r.Context(), time.Since(startTime).Seconds(), metric.WithAttributes(collectionAttr))
}

func (s *Server[RawConfiguration, Configuration, State]) MutationExplain(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
logger := GetLogger(r.Context())
ctx, span := s.telemetry.Tracer.Start(r.Context(), "Mutation Explain", trace.WithSpanKind(trace.SpanKindServer))
defer span.End()

attributes := []attribute.KeyValue{}
_, decodeSpan := s.telemetry.Tracer.Start(ctx, "Decode JSON Body")
defer decodeSpan.End()
var body schema.MutationRequest
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
writeJson(w, logger, http.StatusBadRequest, schema.ErrorResponse{
Message: "failed to decode json request body",
Details: map[string]any{
"cause": err.Error(),
},
})

attributes := []attribute.KeyValue{
attribute.String("status", "failed"),
attribute.String("reason", "json_decode"),
}
span.SetAttributes(attributes...)
s.telemetry.explainCounter.Add(r.Context(), 1, metric.WithAttributes(attributes...))
return
}
decodeSpan.End()

var operationNames []string
for _, op := range body.Operations {
operationNames = append(operationNames, op.Name)
}
collectionAttr := attribute.String("operations", strings.Join(operationNames, ","))
attributes = append(attributes, collectionAttr)
span.SetAttributes(attributes...)
execCtx, execSpan := s.telemetry.Tracer.Start(ctx, "Execute Explain")
defer execSpan.End()

response, err := s.connector.MutationExplain(execCtx, s.configuration, s.state, &body)
if err != nil {
status := writeError(w, logger, err)
statusAttributes := []attribute.KeyValue{
Expand Down Expand Up @@ -349,9 +412,10 @@ func (s *Server[RawConfiguration, Configuration, State]) buildHandler() *http.Se
router.Use("/capabilities", http.MethodGet, s.withAuth(s.GetCapabilities))
router.Use("/schema", http.MethodGet, s.withAuth(s.GetSchema))
router.Use("/query", http.MethodPost, s.withAuth(s.Query))
router.Use("/explain", http.MethodPost, s.withAuth(s.Explain))
router.Use("/query/explain", http.MethodPost, s.withAuth(s.QueryExplain))
router.Use("/mutation/explain", http.MethodPost, s.withAuth(s.MutationExplain))
router.Use("/mutation", http.MethodPost, s.withAuth(s.Mutation))
router.Use("/health", http.MethodGet, s.withAuth(s.Health))
router.Use("/health", http.MethodGet, s.Health)
router.Use("/metrics", http.MethodGet, s.withAuth(promhttp.Handler().ServeHTTP))

return router.Build()
Expand Down
18 changes: 11 additions & 7 deletions connector/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type mockState struct{}
type mockConnector struct{}

var mockCapabilities = schema.CapabilitiesResponse{
Versions: "^0.1.0",
Version: "^0.1.0",
Capabilities: schema.Capabilities{
Query: schema.QueryCapabilities{
Aggregates: schema.LeafCapability{},
Expand All @@ -48,10 +48,8 @@ var mockSchema = schema.SchemaResponse{
ScalarTypes: schema.SchemaResponseScalarTypes{
"String": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{
"like": schema.ComparisonOperatorDefinition{
ArgumentType: schema.NewNamedType("String").Encode(),
},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{
"like": schema.NewComparisonOperatorCustom(schema.NewNamedType("String")).Encode(),
},
},
"Int": schema.ScalarType{
Expand All @@ -63,7 +61,7 @@ var mockSchema = schema.SchemaResponse{
ResultType: schema.NewNullableNamedType("Int").Encode(),
},
},
ComparisonOperators: schema.ScalarTypeComparisonOperators{},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{},
},
},
ObjectTypes: schema.SchemaResponseObjectTypes{
Expand Down Expand Up @@ -157,7 +155,13 @@ func (mc *mockConnector) GetCapabilities(configuration *mockConfiguration) *sche
func (mc *mockConnector) GetSchema(configuration *mockConfiguration) (*schema.SchemaResponse, error) {
return &mockSchema, nil
}
func (mc *mockConnector) Explain(ctx context.Context, configuration *mockConfiguration, state *mockState, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
func (mc *mockConnector) QueryExplain(ctx context.Context, configuration *mockConfiguration, state *mockState, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
return &schema.ExplainResponse{
Details: schema.ExplainResponseDetails{},
}, nil
}

func (mc *mockConnector) MutationExplain(ctx context.Context, configuration *mockConfiguration, state *mockState, request *schema.MutationRequest) (*schema.ExplainResponse, error) {
return &schema.ExplainResponse{
Details: schema.ExplainResponseDetails{},
}, nil
Expand Down
10 changes: 8 additions & 2 deletions connector/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,17 @@ type Connector[RawConfiguration any, Configuration any, State any] interface {
// [schema endpoint]: https://hasura.github.io/ndc-spec/specification/schema/index.html
GetSchema(configuration *Configuration) (*schema.SchemaResponse, error)

// Explain a query by creating an execution plan.
// QueryExplain explains a query by creating an execution plan.
// This function implements the [explain endpoint] from the NDC specification.
//
// [explain endpoint]: https://hasura.github.io/ndc-spec/specification/explain.html
Explain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error)
QueryExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error)

// QueryExplain explains a mutation by creating an execution plan.
// This function implements the [explain endpoint] from the NDC specification.
//
// [explain endpoint]: https://hasura.github.io/ndc-spec/specification/explain.html
MutationExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.MutationRequest) (*schema.ExplainResponse, error)

// Execute a mutation.
//
Expand Down
10 changes: 7 additions & 3 deletions example/codegen/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (mc *Connector) HealthCheck(ctx context.Context, configuration *Configurati

func (mc *Connector) GetCapabilities(configuration *Configuration) *schema.CapabilitiesResponse {
return &schema.CapabilitiesResponse{
Versions: "^0.1.0",
Version: "^0.1.0",
Capabilities: schema.Capabilities{
Query: schema.QueryCapabilities{
Variables: schema.LeafCapability{},
Expand All @@ -49,6 +49,10 @@ func (mc *Connector) GetCapabilities(configuration *Configuration) *schema.Capab
}
}

func (mc *Connector) Explain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
return nil, schema.NotSupportedError("explain has not been supported yet", nil)
func (mc *Connector) QueryExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
return nil, schema.NotSupportedError("query explain has not been supported yet", nil)
}

func (mc *Connector) MutationExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.MutationRequest) (*schema.ExplainResponse, error) {
return nil, schema.NotSupportedError("mutation explain has not been supported yet", nil)
}
16 changes: 10 additions & 6 deletions example/reference/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (mc *Connector) HealthCheck(ctx context.Context, configuration *Configurati

func (mc *Connector) GetCapabilities(configuration *Configuration) *schema.CapabilitiesResponse {
return &schema.CapabilitiesResponse{
Versions: "^0.1.0",
Version: "^0.1.0",
Capabilities: schema.Capabilities{
Query: schema.QueryCapabilities{
Aggregates: schema.LeafCapability{},
Expand All @@ -104,10 +104,8 @@ func (mc *Connector) GetSchema(configuration *Configuration) (*schema.SchemaResp
ScalarTypes: schema.SchemaResponseScalarTypes{
"String": schema.ScalarType{
AggregateFunctions: schema.ScalarTypeAggregateFunctions{},
ComparisonOperators: schema.ScalarTypeComparisonOperators{
"like": schema.ComparisonOperatorDefinition{
ArgumentType: schema.NewNamedType("String").Encode(),
},
ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{
"like": schema.NewComparisonOperatorCustom(schema.NewNamedType("String")).Encode(),
},
},
"Int": schema.ScalarType{
Expand Down Expand Up @@ -224,7 +222,13 @@ func (mc *Connector) GetSchema(configuration *Configuration) (*schema.SchemaResp
}, nil
}

func (mc *Connector) Explain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
func (mc *Connector) QueryExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.QueryRequest) (*schema.ExplainResponse, error) {
return &schema.ExplainResponse{
Details: schema.ExplainResponseDetails{},
}, nil
}

func (mc *Connector) MutationExplain(ctx context.Context, configuration *Configuration, state *State, request *schema.MutationRequest) (*schema.ExplainResponse, error) {
return &schema.ExplainResponse{
Details: schema.ExplainResponseDetails{},
}, nil
Expand Down
Loading

0 comments on commit c6d5337

Please sign in to comment.