Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import graphql.schema.idl.errors.TypeRedefinitionError;
import graphql.util.FpKit;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
Expand All @@ -47,7 +48,7 @@
* a graphql schema definition file via {@link SchemaParser#parse(String)}
*/
@PublicApi
public class TypeDefinitionRegistry {
public class TypeDefinitionRegistry implements Serializable {

private final Map<String, List<ObjectTypeExtensionDefinition>> objectTypeExtensions = new LinkedHashMap<>();
private final Map<String, List<InterfaceTypeExtensionDefinition>> interfaceTypeExtensions = new LinkedHashMap<>();
Expand Down Expand Up @@ -418,7 +419,7 @@ public boolean hasType(TypeName typeName) {
return types.containsKey(name) || ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(name) || scalarTypes.containsKey(name) || objectTypeExtensions.containsKey(name);
}

public Optional<TypeDefinition> getType(Type type) {
public Optional<TypeDefinition> getType(Type type) {
String typeName = TypeInfo.typeInfo(type).getName();
return getType(typeName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import graphql.language.ScalarTypeDefinition
import graphql.language.ScalarTypeExtensionDefinition
import graphql.language.SchemaDefinition
import graphql.language.Type
import graphql.language.TypeDefinition
import graphql.language.TypeName
import graphql.language.UnionTypeDefinition
import graphql.language.UnionTypeExtensionDefinition
Expand All @@ -26,10 +27,11 @@ import spock.lang.Unroll

class TypeDefinitionRegistryTest extends Specification {

TypeDefinitionRegistry parse(String spec) {
static TypeDefinitionRegistry parse(String spec) {
new SchemaParser().parse(spec)
}


def "test default scalars are locked in"() {

def registry = new TypeDefinitionRegistry()
Expand Down Expand Up @@ -931,4 +933,69 @@ class TypeDefinitionRegistryTest extends Specification {
error.isPresent()
error.get().getMessage().contains("tried to redefine existing 'bar' type")
}

def "can be serialized and hence cacheable"() {
def sdl = '''
"the schema"
schema {
query : Q
}

"the query type"
type Q {
field( arg : String! = "default") : FieldType @deprecated(reason : "no good")
}

interface FieldType {
f : UnionType
}

type FieldTypeImpl implements FieldType {
f : UnionType
}

union UnionType = Foo | Bar

type Foo {
foo : String
}

type Bar {
bar : String
}
'''
def registryOut = new SchemaParser().parse(sdl)

when:

TypeDefinitionRegistry registryIn = serialise(registryOut)

then:
TypeDefinition typeIn = registryIn.getType(typeName).get()
TypeDefinition typeOut = registryOut.getType(typeName).get()
typeIn.isEqualTo(typeOut)

where:
typeName | _
"Q" | _
"FieldType" | _
"FieldTypeImpl" | _
"UnionType" | _
"Foo" | _
"Bar" | _
}

static TypeDefinitionRegistry serialise(TypeDefinitionRegistry registryOut) {
ByteArrayOutputStream baOS = new ByteArrayOutputStream()
ObjectOutputStream oos = new ObjectOutputStream(baOS)

oos.writeObject(registryOut)

ByteArrayInputStream baIS = new ByteArrayInputStream(baOS.toByteArray())
ObjectInputStream ois = new ObjectInputStream(baIS)

ois.readObject() as TypeDefinitionRegistry
}


}
28 changes: 28 additions & 0 deletions src/test/java/benchmark/BenchmarkUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package benchmark;

import com.google.common.io.Files;

import java.io.File;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.concurrent.Callable;

public class BenchmarkUtils {

static String loadResource(String name) {
return asRTE(() -> {
URL resource = BenchmarkUtils.class.getClassLoader().getResource(name);
return String.join("\n", Files.readLines(new File(resource.toURI()), Charset.defaultCharset()));

});
}

static <T> T asRTE(Callable<T> callable) {
try {
return callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package benchmark;

import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.jetbrains.annotations.NotNull;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.TimeUnit;

import static benchmark.BenchmarkUtils.asRTE;

/**
* This benchmarks {@link graphql.schema.idl.TypeDefinitionRegistry} parsing and serialisation
* <p>
* See https://github.com/openjdk/jmh/tree/master/jmh-samples/src/main/java/org/openjdk/jmh/samples/ for more samples
* on what you can do with JMH
* <p>
* You MUST have the JMH plugin for IDEA in place for this to work : https://github.com/artyushov/idea-jmh-plugin
* <p>
* Install it and then just hit "Run" on a certain benchmark method
*/
@Warmup(iterations = 2, time = 5, batchSize = 3)
@Measurement(iterations = 3, time = 10, batchSize = 4)
public class TypeDefinitionParserVersusSerializeBenchMark {

static SchemaParser schemaParser = new SchemaParser();
static String SDL = BenchmarkUtils.loadResource("large-schema-2.graphqls");
static TypeDefinitionRegistry registryOut = schemaParser.parse(SDL);
static ByteArrayOutputStream baOS = serialisedRegistryStream(registryOut);

@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public void benchMarkParsing(Blackhole blackhole) {
blackhole.consume(schemaParser.parse(SDL));
}

@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public void benchMarkSerializing(Blackhole blackhole) {
blackhole.consume(serialise());
}

static TypeDefinitionRegistry serialise() {
return asRTE(() -> {

ByteArrayInputStream baIS = new ByteArrayInputStream(baOS.toByteArray());
ObjectInputStream ois = new ObjectInputStream(baIS);

return (TypeDefinitionRegistry) ois.readObject();
});
}

@NotNull
private static ByteArrayOutputStream serialisedRegistryStream(TypeDefinitionRegistry registryOut) {
return asRTE(() -> {
ByteArrayOutputStream baOS = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baOS);

oos.writeObject(registryOut);
return baOS;
});
}
}