-
Notifications
You must be signed in to change notification settings - Fork 843
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
Concurrently resolve fields #132
Conversation
…ten by multiple routines/threads later
* sogko/0.5.0: (32 commits) RFC: Return type overlap validation Tests for `NewDirectives()` for better coverage Clean up redundant code in `completeValueCatchingError` - `completeValue` would already have resolved the value for `func() interface{}` Add tests for type comparators Spec compliant @skip/@include. Fix bug where @include directive is ignored if @Skip is present. Test that `executor` threads `RootValue` correctly - Similar to `context` test Improve coercion error messages [RFC] Add explicit context arg to graphql execution Add GraphQLSchema types field Removed logs Follow up to: Move getTypeOf to executor and rename to defaultResolveTypeFn to mirror defaultResolveFn Add tests for default resolve function. Restored deprecated fields in `directives` in introspective query for coverage. Should be removed once `onOperation`, `onFragment`, `onField` are dropped from spec. Move getTypeOf to execute.js and rename to defaultResolveTypeFn to mirror defaultResolveFn Remove unused function parameters Remove unused function parameters Minor follow-up to graphql-go#311 [RFC] Add Schema Definition to IDL. Updating schema parser to more closely match current state of RFC ...
Commit: 6e736bf4733ada6aa15943c0529ed126e8dd8ef1 [6e736bf] Parents: 86db7340be Author: Lee Byron <[email protected]> Date: 8 April 2016 at 9:51:04 AM SGT Labels: HEAD
Commit: cbded829525a68b9e0dab61621992cbf01348981 [cbded82] Parents: dd02973028 Author: Zhaojun Zhang <[email protected]> Date: 26 April 2016 at 2:04:47 AM SGT Committer: Lee Byron <[email protected]>
graphql/graphql-js#364 Commit: 0b72e7038761bec9fb5319cc08ea93ff8b071a9c [0b72e70] Parents: cbded82952 Author: Mike Solomon <[email protected]> Date: 26 April 2016 at 2:37:25 AM SGT Committer: Lee Byron <[email protected]>
graphql/graphql-js#363 * Improve validation error message when field names conflict * Remove extra hint and add unit test
…raphql-go#355) * Add suggestionList to return strings based on how simular they are to the input * Suggests valid fields in `FieldsOnCorrectType` * Suggest argument names * Suggested valid type names * Fix flow and unit test * addressed comments in PR: move file, update comment, filter out more options, remove redundant warning * fix typos * fix lint Commit: 5bc1b2541d1b5767de4016e10ae77021f81310fc [5bc1b25] Parents: 4b08c36e86 Author: Yuzhi <[email protected]> Date: 27 April 2016 at 2:48:45 AM SGT Committer: Lee Byron <[email protected]>
- `quoteStrings` already defined outside on package scope
Commit: 30a783a2a4f100cad0f31085284895bf51aa565a [30a783a] Parents: 5bc1b2541d Author: Lee Byron <[email protected]> Date: 27 April 2016 at 8:49:33 AM SGT
This fixes a bug where an empty "block" list could be skipped by the printer. Commit: ea5b241487c884edb561b12e0a92e947107bbfc1 [ea5b241] Parents: ec05b5404b Author: Lee Byron <[email protected]> Date: 5 May 2016 at 7:26:11 AM SGT Commit Date: 5 May 2016 at 7:26:13 AM SGT
Commit: 88cf354cd65e37fa0793600f6f2a3e6d1b29d21f [88cf354] Parents: 2ac41f6f19 Author: Lee Byron <[email protected]> Date: 7 May 2016 at 3:09:16 AM SGT
Commit: 71b6a4aaecf064c7095bca81cc4285fa74ba175e [71b6a4a] Parents: 980bdf403f Author: Lee Byron <[email protected]> Date: 7 May 2016 at 4:26:20 AM SGT
This implements adding directives to the experimental schema language by extending the *locations* a directive can be used. Notice that this provides no semantic meaning to these directives - they are purely a mechanism for annotating an AST - however future directives which contain semantic meaning may be introduced in the future (the first will be `@deprecated`). Commit: 1b6824bc5df15f8edb259d535aa41a81e2a07234 [1b6824b] Parents: 71b6a4aaec Author: Lee Byron <[email protected]> Date: 7 May 2016 at 5:56:25 AM SGT Labels: HEAD
This allows directives to be defined on schema definitions. Commit: 0aa78f61a2dc150b5ea9ee4f50b68a736796f068 [0aa78f6] Parents: 1b6824bc5d Author: Lee Byron <[email protected]> Date: 7 May 2016 at 7:05:27 AM SGT Labels: HEAD
This adds a new directive as part of the experimental schema language: ``` directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE ``` It also adds support for this directive in the schemaPrinter and buildASTSchema. Additionally exports a new helper `specifiedDirectives` which is encoured to be used when addressing the collection of all directives defined by the spec. The `@deprecated` directive is optimistically added to this collection. While it's currently experimental, it will become part of the schema definition language RFC. Commit: 5375c9b20452801b69dba208cac15d32e02ac608 [5375c9b] Parents: 0aa78f61a2 Author: Lee Byron <[email protected]> Date: 9 May 2016 at 5:56:16 AM SGT Labels: HEAD
This adds a new directive as part of the experimental schema language: ``` directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE ``` It also adds support for this directive in the schemaPrinter and buildASTSchema. Additionally exports a new helper `specifiedDirectives` which is encoured to be used when addressing the collection of all directives defined by the spec. The `@deprecated` directive is optimistically added to this collection. While it's currently experimental, it will become part of the schema definition language RFC. Commit: 5375c9b20452801b69dba208cac15d32e02ac608 [5375c9b] Parents: 0aa78f61a2 Author: Lee Byron <[email protected]> Date: 9 May 2016 at 5:56:16 AM SGT Labels: HEAD
…ogko/0.6.0 * 'sogko/0.6.0' of https://github.com/sogko/graphql: Revert back directives to use `var`; `const` not applicable here Deprecated directive (graphql-go#384)
The functions within this validator did not need to close over any state, which allows them to be pure functions. Commit: 3a01fac4623b37eb7efcdece7a2c33ef74750aeb [3a01fac] Parents: 5375c9b204 Author: Lee Byron <[email protected]> Date: 10 May 2016 at 6:12:08 AM SGT Commit Date: 10 May 2016 at 6:12:11 AM SGT Labels: HEAD
Two more functions from the overlapping-fields validator which now accept arguments rather than closing over them locally. Commit: cf9be874228f4e16762b481d0abed5575f5587db [cf9be87] Parents: 3a01fac462 Author: Lee Byron <[email protected]> Date: 10 May 2016 at 6:22:53 AM SGT Commit Date: 10 May 2016 at 6:24:50 AM SGT
…r than fragment AST node Commit: 688a1ee20db01ca80fdec2189298078380d81ed6 [688a1ee] Parents: cf9be87422 Author: Lee Byron <[email protected]> Date: 10 May 2016 at 9:54:10 AM SGT
If we can make opt-in concurrency very easy, I think it could be a good solution. Considering the approach of returning a channel from a resolve function, a helper function could make it very easy and get rid of the boilerplate of listening to channels, re-panicking in the executor goroutine, etc. Resolve: graphql.Parallel(func(params graphql.ResolveParams) (interface{}, error) {
// ...
}) I think it's less obvious how to get easy/clean opt-in concurrency support for the elements of a list, since the resolve function is tied to the list itself, not the elements. Maybe add a field to It would be interesting to look into the overhead of the current approach, e.g. via the new benchmarks (#22). A pool of goroutines could potentially be used to decrease the overhead and limit the number of goroutines. |
Even if the go routine overhead isn't a concern, I see another potential problem with this PR. The best feature I like for graphql is the possibility and simplicity of batching/deduping requests to the backend service (e.g. plugging it with facebook/dataloader), which brings substantial performance benefit. Doing parallel in this way makes it very hard (afaict) to implement such features. If we allow the resolve function to return a channel as @Matthias247 suggested, or a func() (interface{}, error) that I personally prefer, the batching mechanism would be possible to implement (which allow some hook to collect all such promise-like results and dispatch batched requests). The implementation of supporting such promise-like feature might be more complicated though, and I'm still trying to figure it out a way to do it. |
My vote goes to opt-in concurrency. |
Following this discussion, I've made a PR for opt-in parallel resolving of fields and lists: sogko#23 |
I really would like to see this going forward, my use case is the same as @rantav, resolving fields from multiple DB queries which can be executed in parallel. |
* master: gofmt -s executor: add graphql tag Fix ObjectConfig duplicate json tag. Name had a 'description' json tag which was duplicate Minor fix to stop `go vet` from complaining Add 1.7 and tip to build matrix for Go Minor fix to stop `go vet` from complaining README: add Documentation section Fixes tests that was broken with enhancements made to the `lexer` with commit graphql-go#137 Improve lexer performance by using a byte array as source Updated `graphql.Float` coercion - if value type is explicitly `float32`, return `float32` - if value type is explicitly `float64`, return `float64` - if value type is `string`, return `float64` - for everything else, use system-default
* sogko/0.6.0: (34 commits) gofmt -s executor: add graphql tag Fix ObjectConfig duplicate json tag. Name had a 'description' json tag which was duplicate Minor fix to stop `go vet` from complaining Add 1.7 and tip to build matrix for Go Minor fix to stop `go vet` from complaining README: add Documentation section Fixes tests that was broken with enhancements made to the `lexer` with commit graphql-go#137 Improve lexer performance by using a byte array as source Validation: improving overlapping fields quality (graphql-go#386) Validation: context.getFragmentSpreads now accepts selectionSet rather than fragment AST node Factor out more closure functions Factor out closure functions to normal functions Deprecated directive (graphql-go#384) Revert back directives to use `var`; `const` not applicable here Deprecated directive (graphql-go#384) RFC: Directive location: schema definition (graphql-go#382) RFC: Schema Language Directives (graphql-go#376) Update `NewSchema()` to use new exported introspective types Export introspection in public API ...
Any update? |
Any Update? |
Any update? |
Up |
I resolved the conflicts for this branch and created PR sogko#25, but there are still many data races due to the fact that Schema is not safe for concurrent use. |
Is there a specific reason why this hasn't been finished/merged? What is pending? This makes it nearly impossible to be used in a large application with complex graphql structure and even moderate traffic. If there is a clear definition of the rationale/direction and what's currently pending, someone else can pick it up. I'm willing to take a stab at it. |
@chris-ramon Could you have time to take look at this? |
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return func() (interface{}, error) {
// runs within a goroutine
}, nil
},
ch := make(graphql.ResolvePromise, 1)
// ...
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return graphql.ResolvePromise(ch), nil
} An another approach PR against a fork:
Parallel: true,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// runs within a goroutine
}, Which one would match your use cases @appleboy |
Thanks a lot guys! 👍 — Closing this one in favor of #388, you might want to take a look to a real-use case working example that shows the support for concurrent resolvers. |
This PR addresses #106 and probably #119.
This also depends on PR #123 and has updated with changes from that PR.
Relevant commits specifically for this PR:
(The other commits are not related to this PR)
09574d6 Ensure rw-safety of
ExecutionContext.errors
which will be read/written by multiple routines/threads laterUses
sync.RWMutex
to ensure safety ofExecutionContext.errors
.If the executor encounters errors while resolving fields (e.g. from recovering from panic or when
ResolveFn
returns anerror
), it will collect it and add to a list of errors, which will then be returned ingraphql.Result
.Since this will be done concurrently if we use go-routines to resolve fields, this has to be thread-safe.
ab3b083 Experimental implementation of concurrently resolving fields
This change is contained in
executeFields(...)
.For each field to be resolved, create a go-routine to resolve a field.
sync.WaitGroup
is used to wait for all fields to complete.This will happen for each field that has sub-fields as well.
Given the following query:
article
andfeed
will be resolved concurrently.article
:id
andauthor
will be resolved concurrently.article.author
:id
andname
will be resolved concurrently.feed
:title
,body
andauthor
will be resolved concurrently.feed.author
:id
andname
will be resolved concurrently.Cheers!