Skip to content

Commit

Permalink
Sergiy/eng 4747 add composition wrapper to the engine (#725)
Browse files Browse the repository at this point in the history
closes #693
closes #571
  • Loading branch information
devsergiy authored Apr 4, 2024
1 parent f5018fb commit 4ae4680
Show file tree
Hide file tree
Showing 222 changed files with 6,053 additions and 8,247 deletions.
72 changes: 72 additions & 0 deletions .github/workflows/execution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: execution
on:
pull_request:
branches:
- master
paths:
- 'v2/**'
- 'execution/**'
- '.github/workflows/execution.yml'
push:
branches:
- master
paths:
- 'v2/**'
- 'execution/**'
- '.github/workflows/execution.yml'
jobs:
test:
name: Build and test (go ${{ matrix.go }} / ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
go: [ '1.21' ]
os: [ubuntu-latest, windows-latest]
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go }}
uses: actions/setup-go@v4
with:
go-version: ^${{ matrix.go }}
id: go
- name: CI
working-directory: execution
run: make ci
- name: Run tests under race detector
working-directory: execution
if: runner.os != 'Windows' # These are very slow on Windows, skip them
run: make test-race

lint:
name: Linters
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Set up Go 1.21
uses: actions/setup-go@v4
with:
go-version: 1.21
- name: Run linters
uses: golangci/golangci-lint-action@v3
with:
working-directory: execution
version: v1.55.2
args: --timeout=3m
ci:
name: CI Success
if: ${{ always() }}
runs-on: ubuntu-latest
needs: [test, lint]
steps:
- run: exit 1
if: >-
${{
contains(needs.*.result, 'failure')
|| contains(needs.*.result, 'cancelled')
}}
5 changes: 5 additions & 0 deletions .github/workflows/v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ on:
- master
paths-ignore:
- 'v2/**'
- 'execution/**'
- '.github/workflows/v2.yml'
- '.github/workflows/execution.yml'
- 'go.work'
- 'go.work.sum'
push:
branches:
- master
paths-ignore:
- 'v2/**'
- 'execution/**'
- '.github/workflows/v2.yml'
- '.github/workflows/execution.yml'
- 'go.work'
- 'go.sum'
jobs:
Expand Down Expand Up @@ -57,6 +61,7 @@ jobs:
with:
version: v1.55.2
args: --timeout=3m
working-directory: pkg
ci:
name: CI Success
if: ${{ always() }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ jobs:
id: go
- name: CI
working-directory: v2
run: make -f ../Makefile ci
run: make ci
- name: Run tests under race detector
working-directory: v2
if: runner.os != 'Windows' # These are very slow on Windows, skip them
run: make -f ../Makefile test-race
run: make test-race

lint:
name: Linters
Expand Down
41 changes: 17 additions & 24 deletions examples/federation/gateway/datasource_poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"strings"
"sync"
"time"

graphqlDataSource "github.com/wundergraph/graphql-go-tools/pkg/engine/datasource/graphql_datasource"
"github.com/wundergraph/graphql-go-tools/execution/engine"
)

type ServiceConfig struct {
Name string
URL string
WS string
Name string
URL string
WS string
Fallback func(*ServiceConfig) (string, error)
}

Expand Down Expand Up @@ -146,40 +146,33 @@ func (d *DatasourcePollerPoller) updateSDLs(ctx context.Context) {
}

func (d *DatasourcePollerPoller) updateObservers() {
dataSourceConfigs := d.createDatasourceConfig()
subgraphsConfig := d.createSubgraphsConfig()

for i := range d.updateDatasourceObservers {
d.updateDatasourceObservers[i].UpdateDataSources(dataSourceConfigs)
d.updateDatasourceObservers[i].UpdateDataSources(subgraphsConfig)
}
}

func (d *DatasourcePollerPoller) createDatasourceConfig() []graphqlDataSource.Configuration {
dataSourceConfigs := make([]graphqlDataSource.Configuration, 0, len(d.config.Services))
func (d *DatasourcePollerPoller) createSubgraphsConfig() []engine.SubgraphConfiguration {
subgraphConfigs := make([]engine.SubgraphConfiguration, 0, len(d.config.Services))

for _, serviceConfig := range d.config.Services {
sdl, exists := d.sdlMap[serviceConfig.Name]
if !exists {
continue
}

dataSourceConfig := graphqlDataSource.Configuration{
Fetch: graphqlDataSource.FetchConfiguration{
URL: serviceConfig.URL,
Method: http.MethodPost,
},
Subscription: graphqlDataSource.SubscriptionConfiguration{
URL: serviceConfig.WS,
},
Federation: graphqlDataSource.FederationConfiguration{
Enabled: true,
ServiceSDL: sdl,
},
subgraphConfig := engine.SubgraphConfiguration{
Name: serviceConfig.Name,
URL: serviceConfig.URL,
SubscriptionUrl: serviceConfig.WS,
SDL: sdl,
}

dataSourceConfigs = append(dataSourceConfigs, dataSourceConfig)
subgraphConfigs = append(subgraphConfigs, subgraphConfig)
}

return dataSourceConfigs
return subgraphConfigs
}

func (d *DatasourcePollerPoller) fetchServiceSDL(ctx context.Context, serviceURL string) (string, error) {
Expand All @@ -206,7 +199,7 @@ func (d *DatasourcePollerPoller) fetchServiceSDL(ctx context.Context, serviceURL
Errors GQLErr `json:"errors,omitempty"`
}

bs, err := ioutil.ReadAll(resp.Body)
bs, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("read bytes: %v", err)
}
Expand Down
35 changes: 14 additions & 21 deletions examples/federation/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,36 @@ import (

log "github.com/jensneuse/abstractlogger"

graphqlDataSource "github.com/wundergraph/graphql-go-tools/pkg/engine/datasource/graphql_datasource"
"github.com/wundergraph/graphql-go-tools/pkg/graphql"
"github.com/wundergraph/graphql-go-tools/execution/engine"
"github.com/wundergraph/graphql-go-tools/execution/graphql"
)

type DataSourceObserver interface {
UpdateDataSources(dataSourceConfig []graphqlDataSource.Configuration)
UpdateDataSources(subgraphsConfigs []engine.SubgraphConfiguration)
}

type DataSourceSubject interface {
Register(observer DataSourceObserver)
}

type HandlerFactory interface {
Make(schema *graphql.Schema, engine *graphql.ExecutionEngineV2) http.Handler
Make(schema *graphql.Schema, engine *engine.ExecutionEngine) http.Handler
}

type HandlerFactoryFn func(schema *graphql.Schema, engine *graphql.ExecutionEngineV2) http.Handler
type HandlerFactoryFn func(schema *graphql.Schema, engine *engine.ExecutionEngine) http.Handler

func (h HandlerFactoryFn) Make(schema *graphql.Schema, engine *graphql.ExecutionEngineV2) http.Handler {
func (h HandlerFactoryFn) Make(schema *graphql.Schema, engine *engine.ExecutionEngine) http.Handler {
return h(schema, engine)
}

func NewGateway(
ctx context.Context,
gqlHandlerFactory HandlerFactory,
httpClient *http.Client,
logger log.Logger,
) *Gateway {
return &Gateway{
engineCtx: ctx,
gqlHandlerFactory: gqlHandlerFactory,
httpClient: httpClient,
logger: logger,
Expand All @@ -55,6 +57,7 @@ type Gateway struct {

readyCh chan struct{}
readyOnce *sync.Once
engineCtx context.Context
}

func (g *Gateway) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand All @@ -69,33 +72,23 @@ func (g *Gateway) Ready() {
<-g.readyCh
}

func (g *Gateway) UpdateDataSources(newDataSourcesConfig []graphqlDataSource.Configuration) {
ctx := context.Background()
engineConfigFactory := graphql.NewFederationEngineConfigFactory(newDataSourcesConfig, graphqlDataSource.NewBatchFactory(), graphql.WithFederationHttpClient(g.httpClient),
graphql.WithEngineOptions(graphql.WithDisableIntrospection(true)))
func (g *Gateway) UpdateDataSources(subgraphsConfigs []engine.SubgraphConfiguration) {
engineConfigFactory := engine.NewFederationEngineConfigFactory(g.engineCtx, subgraphsConfigs, engine.WithFederationHttpClient(g.httpClient))

schema, err := engineConfigFactory.MergedSchema()
if err != nil {
g.logger.Error("get schema:", log.Error(err))
return
}

datasourceConfig, err := engineConfigFactory.EngineV2Configuration()
engineConfig, err := engineConfigFactory.BuildEngineConfiguration()
if err != nil {
g.logger.Error("get engine config: %v", log.Error(err))
return
}

datasourceConfig.EnableDataLoader(true)

engine, err := graphql.NewExecutionEngineV2(ctx, g.logger, datasourceConfig)
executionEngine, err := engine.NewExecutionEngine(g.engineCtx, g.logger, engineConfig)
if err != nil {
g.logger.Error("create engine: %v", log.Error(err))
return
}

g.mu.Lock()
g.gqlHandler = g.gqlHandlerFactory.Make(schema, engine)
g.gqlHandler = g.gqlHandlerFactory.Make(engineConfig.Schema(), executionEngine)
g.mu.Unlock()

g.readyOnce.Do(func() { close(g.readyCh) })
Expand Down
10 changes: 7 additions & 3 deletions examples/federation/gateway/http/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import (
"github.com/gobwas/ws"
log "github.com/jensneuse/abstractlogger"

"github.com/wundergraph/graphql-go-tools/pkg/graphql"
"github.com/wundergraph/graphql-go-tools/execution/engine"
"github.com/wundergraph/graphql-go-tools/execution/graphql"
)

const (
Expand All @@ -15,23 +16,26 @@ const (

func NewGraphqlHTTPHandler(
schema *graphql.Schema,
engine *graphql.ExecutionEngineV2,
engine *engine.ExecutionEngine,
upgrader *ws.HTTPUpgrader,
logger log.Logger,
enableART bool,
) http.Handler {
return &GraphQLHTTPRequestHandler{
schema: schema,
engine: engine,
wsUpgrader: upgrader,
log: logger,
enableART: enableART,
}
}

type GraphQLHTTPRequestHandler struct {
log log.Logger
wsUpgrader *ws.HTTPUpgrader
engine *graphql.ExecutionEngineV2
engine *engine.ExecutionEngine
schema *graphql.Schema
enableART bool
}

func (g *GraphQLHTTPRequestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand Down
23 changes: 21 additions & 2 deletions examples/federation/gateway/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (

log "github.com/jensneuse/abstractlogger"

"github.com/wundergraph/graphql-go-tools/pkg/graphql"
"github.com/wundergraph/graphql-go-tools/execution/engine"
"github.com/wundergraph/graphql-go-tools/execution/graphql"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
)

const (
Expand All @@ -25,9 +27,26 @@ func (g *GraphQLHTTPRequestHandler) handleHTTP(w http.ResponseWriter, r *http.Re
return
}

var opts []engine.ExecutionOptions

if g.enableART {
tracingOpts := resolve.TraceOptions{
Enable: true,
ExcludePlannerStats: false,
ExcludeRawInputData: false,
ExcludeInput: false,
ExcludeOutput: false,
ExcludeLoadStats: false,
EnablePredictableDebugTimings: false,
IncludeTraceOutputInResponseExtensions: true,
}

opts = append(opts, engine.WithRequestTraceOptions(tracingOpts))
}

buf := bytes.NewBuffer(make([]byte, 0, 4096))
resultWriter := graphql.NewEngineResultWriterFromBuffer(buf)
if err = g.engine.Execute(r.Context(), &gqlRequest, &resultWriter); err != nil {
if err = g.engine.Execute(r.Context(), &gqlRequest, &resultWriter, opts...); err != nil {
g.log.Error("engine.Execute", log.Error(err))
w.WriteHeader(http.StatusInternalServerError)
return
Expand Down
2 changes: 1 addition & 1 deletion examples/federation/gateway/http/ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/gobwas/ws/wsutil"
"github.com/jensneuse/abstractlogger"

"github.com/wundergraph/graphql-go-tools/pkg/subscription"
"github.com/wundergraph/graphql-go-tools/execution/subscription"
)

// WebsocketSubscriptionClient is an actual implementation of the subscritpion client interface.
Expand Down
Loading

0 comments on commit 4ae4680

Please sign in to comment.