Skip to content

Conversation

@bbakerman
Copy link
Member

This is some early work to cache parsed and validated documents by default.

This is discussed in more detailed here #4107

@bbakerman bbakerman added this to the 25.x breaking changes milestone Sep 19, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 19, 2025

Test Results

  326 files    326 suites   3m 31s ⏱️
5 026 tests 5 020 ✅ 6 💤 0 ❌
5 115 runs  5 109 ✅ 6 💤 0 ❌

Results for commit c42baa7.

♻️ This comment has been updated with latest results.

@bbakerman
Copy link
Member Author

I have manually tested a consumer where Caffiene is and is not on the classpath

TypeDefinitionRegistry registry = new SchemaParser().parse("type Query { f : String }");
        RuntimeWiring runtimeWiring = RuntimeWiring.MOCKED_WIRING;
        GraphQLSchema graphQLSchema = new SchemaGenerator().makeExecutableSchema(registry, runtimeWiring);

        GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build();

        for (int i = 1; i <= 5; i++) {
            //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
            // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
            ExecutionInput ei = ExecutionInput.newExecutionInput().query("query q { f }").root(Map.of("f", "F")).build();
            ExecutionResult er = graphQL.execute(ei);
            System.out.println("i" + i + "data :  " + er.getData() + " : errors : " + er.getErrors());
        }
dependencies {
    implementation("com.graphql-java:graphql-java:0.0.0-caching-query-parsing-and-validation-SNAPSHOT")
    implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
}

or

dependencies {
    implementation("com.graphql-java:graphql-java:0.0.0-caching-query-parsing-and-validation-SNAPSHOT")
}

I can confirm the Caffeine detection code works as expected and it does NOT load any Caffeine code unless its present and hence it works as a No Op when caffeine is NOT present but caches when it is present

return CompletableFuture.completedFuture(cacheEntry);
}

}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its surprisingly little code


CaffeineDocumentCache(boolean isCaffeineAvailable) {
if (isCaffeineAvailable) {
CaffeineDocumentCacheOptions options = CaffeineDocumentCacheOptions.getDefaultJvmOptions();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice it never loads an Caffeine code unless Caffeine is on the class path

private static CaffeineDocumentCacheOptions defaultJvmOptions = newOptions()
.expireAfterAccess(EXPIRED_AFTER_ACCESS)
.maxSize(MAX_SIZE)
.build();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an area for more discussion. Should we have simple defaults or try to guess based on a memory heuristic??

private ExecutionIdProvider idProvider = DEFAULT_EXECUTION_ID_PROVIDER;
private Instrumentation instrumentation = null; // deliberate default here
private PreparsedDocumentProvider preparsedDocumentProvider = NoOpPreparsedDocumentProvider.INSTANCE;
private PreparsedDocumentProvider preparsedDocumentProvider = new CachingDocumentProvider();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caching is now on by default. If you dont want it use NoOpPreparsedDocumentProvider.INSTANCE which still exists

@dondonz dondonz modified the milestones: 25.x breaking changes, 26.x Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants