Skip to content

Commit

Permalink
Remove IDs left from execution (#56)
Browse files Browse the repository at this point in the history
* tests no longer have ids

* fixed error reporting in test coverage task

* fixed typo in examples

* added well-type context struct for execution

* execute just takes in an object

* reorder

* fixed tests that should be passing

* added response middlewares to execution

* added docs page on middlewares

* response middlewares are now the gateway's concern

* since filtering id is now a gateway concern executor tests can go back

* dried up gateway tests

* failing tests for scrubbing ids as response middleware

* placeholder for default response middleware to scrub fields

* renamed response middleware to scrub insertion ids

* comment hygiene

* more work on adding scrub fields

* hunch

* query tests pass

* more scrubbing tests

* tests pass
  • Loading branch information
AlecAivazis authored Feb 7, 2019
1 parent 85ab513 commit 60ac978
Show file tree
Hide file tree
Showing 13 changed files with 1,018 additions and 555 deletions.
2 changes: 1 addition & 1 deletion _tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ tests:
test:coverage:
summary: run the tests, generate a coverage report, and report it to coveralls
command: |-
go test -v -covermode=atomic -coverprofile=coverage.out {{ .files }}
go test -v -covermode=atomic -coverprofile=coverage.out {{ .files }} &&
$HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN
build:
Expand Down
6 changes: 6 additions & 0 deletions docs/middlewares.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Middlewares

There are currently two types of middlewares that can modify the gateway:

- RequestMiddleware
- ResponseMiddleware
2 changes: 1 addition & 1 deletion examples/auth/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var forwardUserID = gateway.RequestMiddleware(func(r *http.Request) error {
}

// return the modified request
return r, nil
return nil
})

func main() {
Expand Down
40 changes: 27 additions & 13 deletions execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// Executor is responsible for executing a query plan against the remote
// schemas and returning the result
type Executor interface {
Execute(ctx context.Context, plan *QueryPlan, variables map[string]interface{}) (map[string]interface{}, error)
Execute(ctx *ExecutionContext) (map[string]interface{}, error)
}

// ParallelExecutor executes the given query plan by starting at the root of the plan and
Expand All @@ -28,8 +28,22 @@ type queryExecutionResult struct {
StripNode bool
}

// execution is broken up into two phases:
// - the first walks down the dependency graph execute the network request
// - the second strips the id fields from the response and provides a
// place for certain middlewares to fire

// ExecutionContext is a well-type alternative to context.Context and provides the context
// for a particular execution.
type ExecutionContext struct {
Plan *QueryPlan
Variables map[string]interface{}
RequestContext context.Context
RequestMiddlewares []graphql.NetworkMiddleware
}

// Execute returns the result of the query plan
func (executor *ParallelExecutor) Execute(ctx context.Context, plan *QueryPlan, variables map[string]interface{}) (map[string]interface{}, error) {
func (executor *ParallelExecutor) Execute(ctx *ExecutionContext) (map[string]interface{}, error) {
// a place to store the result
result := map[string]interface{}{}

Expand All @@ -53,14 +67,14 @@ func (executor *ParallelExecutor) Execute(ctx context.Context, plan *QueryPlan,
resultLock := &sync.Mutex{}

// if there are no steps after the root step, there is a problem
if len(plan.RootStep.Then) == 0 {
if len(ctx.Plan.RootStep.Then) == 0 {
return nil, errors.New("was given empty plan")
}

// the root step could have multiple steps that have to happen
for _, step := range plan.RootStep.Then {
for _, step := range ctx.Plan.RootStep.Then {
stepWg.Add(1)
go executeStep(ctx, plan, step, []string{}, resultLock, variables, resultCh, errCh, stepWg)
go executeStep(ctx, ctx.Plan, step, []string{}, resultLock, ctx.Variables, resultCh, errCh, stepWg)
}

// the list of errors we have encountered while executing the plan
Expand Down Expand Up @@ -127,7 +141,7 @@ func (executor *ParallelExecutor) Execute(ctx context.Context, plan *QueryPlan,

// TODO: ugh... so... many... variables...
func executeStep(
ctx context.Context,
ctx *ExecutionContext,
plan *QueryPlan,
step *QueryPlanStep,
insertionPoint []string,
Expand Down Expand Up @@ -189,15 +203,15 @@ func executeStep(
queryResult := map[string]interface{}{}

// if we have middlewares
if mwares := getCtxRequestMiddlewares(ctx); mwares != nil {
if len(ctx.RequestMiddlewares) > 0 {
// if the queryer is a network queryer
if nQueryer, ok := queryer.(*graphql.NetworkQueryer); ok {
queryer = nQueryer.WithMiddlewares(mwares)
queryer = nQueryer.WithMiddlewares(ctx.RequestMiddlewares)
}
}

// fire the query
err := queryer.Query(ctx, &graphql.QueryInput{
err := queryer.Query(ctx.RequestContext, &graphql.QueryInput{
Query: step.QueryString,
QueryDocument: step.QueryDocument,
Variables: variables,
Expand Down Expand Up @@ -623,11 +637,11 @@ func executorGetPointData(point string) (*extractorPointData, error) {
}

// ExecutorFunc wraps a function to be used as an executor.
type ExecutorFunc func(ctx context.Context, plan *QueryPlan, variables map[string]interface{}) (map[string]interface{}, error)
type ExecutorFunc func(ctx *ExecutionContext) (map[string]interface{}, error)

// Execute invokes and returns the internal function
func (e ExecutorFunc) Execute(ctx context.Context, plan *QueryPlan, variables map[string]interface{}) (map[string]interface{}, error) {
return e(ctx, plan, variables)
func (e ExecutorFunc) Execute(ctx *ExecutionContext) (map[string]interface{}, error) {
return e(ctx)
}

// ErrExecutor always returnes the internal error.
Expand All @@ -636,6 +650,6 @@ type ErrExecutor struct {
}

// Execute returns the internet error
func (e *ErrExecutor) Execute(ctx context.Context, plan *QueryPlan, variables map[string]interface{}) (map[string]interface{}, error) {
func (e *ErrExecutor) Execute(ctx *ExecutionContext) (map[string]interface{}, error) {
return nil, e.Error
}
Loading

0 comments on commit 60ac978

Please sign in to comment.