We are pleased to announce the release of graphql-java v22.0.
Thanks to everyone in the community who contributed to the release, whether that was code, helping to report issues, or participating in discussions.
This is a breaking change release.
The graphql-java team takes breaking changes very seriously but in the name of performance we have made some significant breaking changes in this release.
Major Performance Changes
Past releases have been very much performance focused and this one is no different. However, this release is aiming to reduce memory pressure more than reduce pure CPU usage. When the graphql-java engine is running, if it produces less objects it will ultimately run faster because of reduced memory pressure and less garbage to collect.
The engine has been changed in two major ways that reduce memory pressure.
ExecutionResult wrapping
The first was that all values that come back got wrapped internally into a ExecutionResult object where the data attribute was the value. This was a carry over from some very early GraphQL code but was unnecessary and hence has been removed. The follow on effect of this is that some graphql.execution.ExecutionStrategy protected methods and graphql.execution.instrumentation.Instrumentation methods used to receive and return ExecutionResult values and no longer do, which is an API breaking change. We have made this breaking changes in the name of memory pressure performance.
CompletableFuture wrapping
The second major change is that the engine no longer exclusively uses java.util.concurrent.CompletableFutures when composing together results. Let us explain the past code first so we can discuss the new code.
CompletableFuture is a fantastic construct because it represents a promise to a value and it can also hold an exceptional state inside itself. Async programming with CompletableFuture is viral. If stage 1 of some compute process returns a CompletableFuture then stage 2 and 3 and 4 are likely to as well to ensure everything is asynchronous.
We use to take values that were not asynchronous (such as DataFetcher that returned a simple in memory object) and wrap them in a CompletableFuture so that all of the other code composed together using CompletableFuture methods like .thenApply() and .thenCompose and so on. The code is cleaner if you use all CompletableFuture code patterns.
However many objects in a GraphQL request are not asynchronous but rather materialised objects in memory. Scalars, enums and list are often just values immediately available to be used and allocating a CompletableFuture makes the code easier to write but it has a memory pressure cost.
So we have sacrificed cleaner code for more memory performant code.
graphql-java engine graphql.execution.ExecutionStrategy methods now just return Object where that object might be either a CompletableFuture or a materialised value.
Notice we have lost type safety here. In the past this would have only been CompletableFuture<FetchedValue> and hence been both type safe and async composable.
Now the caller of that method has to handle the async case where it might be a CompletableFuture<FetchedValue> AND the materialised value case where it might be a FetchedValue but as most simple fields in GraphQL are in fact materialised values, this is worth the less clean code.
DataFetchers can of course continue to return CompletableFuture values and they will be handled in a polymorphic manner.
The upshot of all this work is that the graphql-java engine allocated way less CompletableFuture values and hence reduces the amount of memory used.
Instrumentation Changes
... (truncated)
Commits
0eec91e Merge pull request #3551 from jbellenger/jbellenger-validate-dir-args
c4df085 Merge pull request #3567 from graphql-java/dependabot/github_actions/gradle/w...
2cf3cc0 Merge pull request #3566 from graphql-java/dependabot/gradle/org.testng-testn...
1d78326 Merge pull request #3565 from graphql-java/strict-mode-runtime-wiring
207bb83 Bump gradle/wrapper-validation-action from 2 to 3
9f613a6 Bump org.testng:testng from 7.10.0 to 7.10.1
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Bumps com.graphql-java:graphql-java from 21.5 to 22.0.
Release notes
Sourced from com.graphql-java:graphql-java's releases.
... (truncated)
Commits
0eec91e
Merge pull request #3551 from jbellenger/jbellenger-validate-dir-argsc4df085
Merge pull request #3567 from graphql-java/dependabot/github_actions/gradle/w...2cf3cc0
Merge pull request #3566 from graphql-java/dependabot/gradle/org.testng-testn...1d78326
Merge pull request #3565 from graphql-java/strict-mode-runtime-wiring207bb83
Bump gradle/wrapper-validation-action from 2 to 39f613a6
Bump org.testng:testng from 7.10.0 to 7.10.1bb82efb
Better testing5a53ec4
strictMode for RuntimeWiring and TypeRuntimeWiring7f13678
Merge pull request #3564 from graphql-java/add-dataloader-3.3.0b2dc510
Dataloader 3.3.0Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show