craftercms / craftercms

Parent project for Crafter CMS. Issue tracking across all repositories and global builds.
GNU General Public License v3.0
288 stars 98 forks source link

Bump com.graphql-java:graphql-java from 21.3 to 22.0 #6829

Closed dependabot[bot] closed 1 month ago

dependabot[bot] commented 1 month ago

Bumps com.graphql-java:graphql-java from 21.3 to 22.0.

Release notes

Sourced from com.graphql-java:graphql-java's releases.

22.0

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.

    private Object /*CompletableFuture<FetchedValue> | FetchedValue>*/
       fetchField(GraphQLFieldDefinition fieldDef, ExecutionContext executionContext, ExecutionStrategyParameters parameters) {

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
  • bb82efb Better testing
  • 5a53ec4 strictMode for RuntimeWiring and TypeRuntimeWiring
  • 7f13678 Merge pull request #3564 from graphql-java/add-dataloader-3.3.0
  • b2dc510 Dataloader 3.3.0
  • Additional commits viewable in compare view


Dependabot compatibility score

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)